Address review comments wasm/support to wasm/src
[mono-project.git] / sdks / wasm / src / binding_support.js
blob2b945f53e510ef659fc88daae1dc2778dc543a8d
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");
96                         this.get_date_value = get_method ("GetDateValue");
97                         this.create_date_time = get_method ("CreateDateTime");
99                         this.object_to_enum = get_method ("ObjectToEnum");
100                         this.init = true;
101                 },              
103                 get_js_obj: function (js_handle) {
104                         if (js_handle > 0)
105                                 return this.mono_wasm_require_handle(js_handle);
106                         return null;
107                 },
108                 
109                 //FIXME this is wastefull, we could remove the temp malloc by going the UTF16 route
110                 //FIXME this is unsafe, cuz raw objects could be GC'd.
111                 conv_string: function (mono_obj) {
112                         if (mono_obj == 0)
113                                 return null;
114                         var raw = this.mono_string_get_utf8 (mono_obj);
115                         var res = Module.UTF8ToString (raw);
116                         Module._free (raw);
118                         return res;
119                 },
121                 is_nested_array: function (ele) {
122                         return this.call_method (this.is_simple_array, null, "mi", [ ele ]);
123                 },
125                 mono_array_to_js_array: function (mono_array) {
126                         if (mono_array == 0)
127                                 return null;
129                         var res = [];
130                         var len = this.mono_array_length (mono_array);
131                         for (var i = 0; i < len; ++i)
132                         {
133                                 var ele = this.mono_array_get (mono_array, i);
134                                 if (this.is_nested_array(ele))
135                                         res.push(this.mono_array_to_js_array(ele));
136                                 else
137                                         res.push (this.unbox_mono_obj (ele));
138                         }
140                         return res;
141                 },
143                 js_array_to_mono_array: function (js_array) {
144                         var mono_array = this.mono_obj_array_new (js_array.length);
145                         for (var i = 0; i < js_array.length; ++i) {
146                                 this.mono_obj_array_set (mono_array, i, this.js_to_mono_obj (js_array [i]));
147                         }
148                         return mono_array;
149                 },
151                 unbox_mono_obj: function (mono_obj) {
152                         if (mono_obj == 0)
153                                 return undefined;
154                         var type = this.mono_get_obj_type (mono_obj);
155                         //See MARSHAL_TYPE_ defines in driver.c
156                         switch (type) {
157                         case 1: // int
158                                 return this.mono_unbox_int (mono_obj);
159                         case 2: // float
160                                 return this.mono_unbox_float (mono_obj);
161                         case 3: //string
162                                 return this.conv_string (mono_obj);
163                         case 4: //vts
164                                 throw new Error ("no idea on how to unbox value types");
165                         case 5: { // delegate
166                                 var obj = this.extract_js_obj (mono_obj);
167                                 return function () {
168                                         return BINDING.invoke_delegate (obj, arguments);
169                                 };
170                         }
171                         case 6: {// Task
173                                 if (typeof Promise === "undefined" || typeof Promise.resolve === "undefined")
174                                         throw new Error ("Promises are not supported thus C# Tasks can not work in this context.");
176                                 var obj = this.extract_js_obj (mono_obj);
177                                 var cont_obj = null;
178                                 var promise = new Promise (function (resolve, reject) {
179                                         cont_obj = {
180                                                 resolve: resolve,
181                                                 reject: reject
182                                         };
183                                 });
185                                 this.call_method (this.setup_js_cont, null, "mo", [ mono_obj, cont_obj ]);
186                                 obj.__mono_js_cont__ = cont_obj.__mono_gchandle__;
187                                 cont_obj.__mono_js_task__ = obj.__mono_gchandle__;
188                                 return promise;
189                         }
191                         case 7: // ref type
192                                 return this.extract_js_obj (mono_obj);
194                         case 8: // bool
195                                 return this.mono_unbox_int (mono_obj) != 0;
197                         case 9: // enum
199                                 if(this.mono_wasm_marshal_enum_as_int)
200                                 {
201                                         return this.mono_unbox_enum (mono_obj);
202                                 }
203                                 else
204                                 {
205                                         enumValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]);
206                                 }
208                                 return enumValue;
211                         case 11: 
212                         case 12: 
213                         case 13: 
214                         case 14: 
215                         case 15: 
216                         case 16: 
217                         case 17: 
218                         case 18:
219                         {
220                                 throw new Error ("Marshalling of primitive arrays are not supported.  Use the corresponding TypedArray instead.");
221                         }
222                         case 20: // clr .NET DateTime
223                                 var dateValue = this.call_method(this.get_date_value, null, "md", [ mono_obj ]);
224                                 return new Date(dateValue);
225                         case 21: // clr .NET DateTimeOffset
226                                 var dateoffsetValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]);
227                                 return dateoffsetValue;
228                         default:
229                                 throw new Error ("no idea on how to unbox object kind " + type);
230                         }
231                 },
233                 create_task_completion_source: function () {
234                         return this.call_method (this.create_tcs, null, "i", [ -1 ]);
235                 },
237                 set_task_result: function (tcs, result) {
238                         tcs.is_mono_tcs_result_set = true;
239                         this.call_method (this.set_tcs_result, null, "oo", [ tcs, result ]);
240                         if (tcs.is_mono_tcs_task_bound)
241                                 this.free_task_completion_source(tcs);
242                 },
244                 set_task_failure: function (tcs, reason) {
245                         tcs.is_mono_tcs_result_set = true;
246                         this.call_method (this.set_tcs_failure, null, "os", [ tcs, reason.toString () ]);
247                         if (tcs.is_mono_tcs_task_bound)
248                                 this.free_task_completion_source(tcs);
249                 },
251                 // https://github.com/Planeshifter/emscripten-examples/blob/master/01_PassingArrays/sum_post.js
252                 js_typedarray_to_heap: function(typedArray){
253                         var numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT;
254                         var ptr = Module._malloc(numBytes);
255                         var heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes);
256                         heapBytes.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, numBytes));
257                         return heapBytes;
258                 },
259                 js_to_mono_obj: function (js_obj) {
260                         this.bindings_lazy_init ();
262                         if (js_obj == null || js_obj == undefined)
263                                 return 0;
264                         if (typeof js_obj === 'number') {
265                                 if (parseInt(js_obj) == js_obj)
266                                         return this.call_method (this.box_js_int, null, "im", [ js_obj ]);
267                                 return this.call_method (this.box_js_double, null, "dm", [ js_obj ]);
268                         }
269                         if (typeof js_obj === 'string')
270                                 return this.js_string_to_mono_string (js_obj);
272                         if (typeof js_obj === 'boolean')
273                                 return this.call_method (this.box_js_bool, null, "im", [ js_obj ]);
275                         if (Promise.resolve(js_obj) === js_obj) {
276                                 var the_task = this.try_extract_mono_obj (js_obj);
277                                 if (the_task)
278                                         return the_task;
279                                 var tcs = this.create_task_completion_source ();
281                                 js_obj.then (function (result) {
282                                         BINDING.set_task_result (tcs, result);
283                                 }, function (reason) {
284                                         BINDING.set_task_failure (tcs, reason);
285                                 })
287                                 return this.get_task_and_bind (tcs, js_obj);
288                         }
290                         if (js_obj.constructor.name === "Date")
291                                 // We may need to take into account the TimeZone Offset
292                                 return this.call_method(this.create_date_time, null, "dm", [ js_obj.getTime() ]);
294                         return this.extract_mono_obj (js_obj);
295                 },
296                 js_typed_array_to_array : function (js_obj) {
298                         // JavaScript typed arrays are array-like objects and provide a mechanism for accessing 
299                         // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays 
300                         // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
301                         //  is an object representing a chunk of data; it has no format to speak of, and offers no 
302                         // mechanism for accessing its contents. In order to access the memory contained in a buffer, 
303                         // you need to use a view. A view provides a context â€” that is, a data type, starting offset, 
304                         // and number of elements â€” that turns the data into an actual typed array.
305                         // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
306                         if (!!(js_obj.buffer instanceof ArrayBuffer && js_obj.BYTES_PER_ELEMENT)) 
307                         {
308                                 var arrayType = 0;      
309                                 if (js_obj instanceof Int8Array)
310                                         arrayType = 11;
311                                 if (js_obj instanceof Uint8Array)
312                                         arrayType = 12;
313                                 if (js_obj instanceof Uint8ClampedArray)
314                                         arrayType = 12;
315                                 if (js_obj instanceof Int16Array)
316                                         arrayType = 13;
317                                 if (js_obj instanceof Uint16Array)
318                                         arrayType = 14;
319                                 if (js_obj instanceof Int32Array)
320                                         arrayType = 15;
321                                 if (js_obj instanceof Uint32Array)
322                                         arrayType = 16;
323                                 if (js_obj instanceof Float32Array)
324                                         arrayType = 17;
325                                 if (js_obj instanceof Float64Array)
326                                         arrayType = 18;
328                                 var heapBytes = this.js_typedarray_to_heap(js_obj);
329                                 var bufferArray = this.mono_typed_array_new(heapBytes.byteOffset, js_obj.length, js_obj.BYTES_PER_ELEMENT, arrayType);
330                                 Module._free(heapBytes.byteOffset);
331                                 return bufferArray;
332                         }
333                         else {
334                                 throw new Error("Object '" + js_obj + "' is not a typed array");
335                         } 
338                 },
339                 // Copy the existing typed array to the heap pointed to by the pinned array address
340                 //       typed array memory -> copy to heap -> address of managed pinned array
341                 typedarray_copy_to : function (typed_array, pinned_array, begin, end, bytes_per_element) {
343                         // JavaScript typed arrays are array-like objects and provide a mechanism for accessing 
344                         // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays 
345                         // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
346                         //  is an object representing a chunk of data; it has no format to speak of, and offers no 
347                         // mechanism for accessing its contents. In order to access the memory contained in a buffer, 
348                         // you need to use a view. A view provides a context â€” that is, a data type, starting offset, 
349                         // and number of elements â€” that turns the data into an actual typed array.
350                         // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
351                         if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT)) 
352                         {
353                                 // Some sanity checks of what is being asked of us
354                                 // lets play it safe and throw an error here instead of assuming to much.
355                                 // Better safe than sorry later
356                                 if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
357                                         throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
359                                 // how much space we have to work with
360                                 var num_of_bytes = (end - begin) * bytes_per_element;
361                                 // how much typed buffer space are we talking about
362                                 var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
363                                 // only use what is needed.
364                                 if (num_of_bytes > view_bytes)
365                                         num_of_bytes = view_bytes;
367                                 // offset index into the view
368                                 var offset = begin * bytes_per_element;
370                                 // Create a view over the heap pointed to by the pinned array address
371                                 var heapBytes = new Uint8Array(Module.HEAPU8.buffer, pinned_array + offset, num_of_bytes);
372                                 // Copy the bytes of the typed array to the heap.
373                                 heapBytes.set(new Uint8Array(typed_array.buffer, typed_array.byteOffset, num_of_bytes));
375                                 return num_of_bytes;
376                         }
377                         else {
378                                 throw new Error("Object '" + typed_array + "' is not a typed array");
379                         } 
381                 },      
382                 // Copy the pinned array address from pinned_array allocated on the heap to the typed array.
383                 //       adress of managed pinned array -> copy from heap -> typed array memory
384                 typedarray_copy_from : function (typed_array, pinned_array, begin, end, bytes_per_element) {
386                         // JavaScript typed arrays are array-like objects and provide a mechanism for accessing 
387                         // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays 
388                         // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
389                         //  is an object representing a chunk of data; it has no format to speak of, and offers no 
390                         // mechanism for accessing its contents. In order to access the memory contained in a buffer, 
391                         // you need to use a view. A view provides a context â€” that is, a data type, starting offset, 
392                         // and number of elements â€” that turns the data into an actual typed array.
393                         // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
394                         if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT)) 
395                         {
396                                 // Some sanity checks of what is being asked of us
397                                 // lets play it safe and throw an error here instead of assuming to much.
398                                 // Better safe than sorry later
399                                 if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
400                                         throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
402                                 // how much space we have to work with
403                                 var num_of_bytes = (end - begin) * bytes_per_element;
404                                 // how much typed buffer space are we talking about
405                                 var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
406                                 // only use what is needed.
407                                 if (num_of_bytes > view_bytes)
408                                         num_of_bytes = view_bytes;
410                                 // Create a new view for mapping
411                                 var typedarrayBytes = new Uint8Array(typed_array.buffer, 0, num_of_bytes);
412                                 // offset index into the view
413                                 var offset = begin * bytes_per_element;
414                                 // Set view bytes to value from HEAPU8
415                                 typedarrayBytes.set(Module.HEAPU8.subarray(pinned_array + offset, pinned_array + offset + num_of_bytes));
416                                 return num_of_bytes;
417                         }
418                         else {
419                                 throw new Error("Object '" + typed_array + "' is not a typed array");
420                         } 
422                 },      
423                 // Creates a new typed array from pinned array address from pinned_array allocated on the heap to the typed array.
424                 //       adress of managed pinned array -> copy from heap -> typed array memory
425                 typed_array_from : function (pinned_array, begin, end, bytes_per_element, type) {
427                         // typed array
428                         var newTypedArray = 0;
430                         switch (type)
431                         {
432                                 case 5: 
433                                         newTypedArray = new Int8Array(end - begin);
434                                         break;
435                                 case 6: 
436                                         newTypedArray = new Uint8Array(end - begin);
437                                         break;
438                                 case 7: 
439                                         newTypedArray = new Int16Array(end - begin);
440                                         break;
441                                 case 8: 
442                                         newTypedArray = new Uint16Array(end - begin);
443                                         break;
444                                 case 9: 
445                                         newTypedArray = new Int32Array(end - begin);
446                                         break;
447                                 case 10: 
448                                         newTypedArray = new Uint32Array(end - begin);
449                                         break;
450                                 case 13: 
451                                         newTypedArray = new Float32Array(end - begin);
452                                         break;
453                                 case 14:
454                                         newTypedArray = new Float64Array(end - begin);
455                                         break;
456                                 case 15:  // This is a special case because the typed array is also byte[]
457                                         newTypedArray = new Uint8ClampedArray(end - begin);
458                                         break;
459                         }
461                         this.typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element);
462                         return newTypedArray;
463                 },              
464                 js_to_mono_enum: function (method, parmIdx, js_obj) {
465                         this.bindings_lazy_init ();
466     
467                         if (js_obj === null || typeof js_obj === "undefined")
468                                 return 0;
470                         var monoObj = this.js_to_mono_obj(js_obj);
471                         // Check enum contract
472                         var monoEnum = this.call_method(this.object_to_enum, null, "iimm", [ method, parmIdx, monoObj ])
473                         // return the unboxed enum value.
474                         return this.mono_unbox_enum(monoEnum);
475                 },
476                 wasm_binding_obj_new: function (js_obj_id, type)
477                 {
478                         return this.call_method (this.bind_js_obj, null, "io", [js_obj_id, type]);
479                 },
480                 wasm_bind_existing: function (mono_obj, js_id)
481                 {
482                         return this.call_method (this.bind_existing_obj, null, "mi", [mono_obj, js_id]);
483                 },
485                 wasm_bind_core_clr_obj: function (js_id, gc_handle)
486                 {
487                         return this.call_method (this.bind_core_clr_obj, null, "ii", [js_id, gc_handle]);
488                 },
490                 wasm_unbind_js_obj: function (js_obj_id)
491                 {
492                         this.call_method (this.unbind_js_obj, null, "i", [js_obj_id]);
493                 },              
495                 wasm_unbind_js_obj_and_free: function (js_obj_id)
496                 {
497                         this.call_method (this.unbind_js_obj_and_free, null, "i", [js_obj_id]);
498                 },              
500                 wasm_get_js_id: function (mono_obj)
501                 {
502                         return this.call_method (this.get_js_id, null, "m", [mono_obj]);
503                 },
505                 wasm_get_raw_obj: function (gchandle)
506                 {
507                         return this.call_method (this.get_raw_mono_obj, null, "im", [gchandle]);
508                 },
510                 try_extract_mono_obj:function (js_obj) {
511                         if (js_obj === null || typeof js_obj === "undefined" || typeof js_obj.__mono_gchandle__ === "undefined")
512                                 return 0;
513                         return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
514                 },
516                 mono_method_get_call_signature: function(method) {
517                         this.bindings_lazy_init ();
519                         return this.call_method (this.get_call_sig, null, "i", [ method ]);
520                 },
522                 get_task_and_bind: function (tcs, js_obj) {
523                         var gc_handle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
524                         var task_gchandle = this.call_method (this.tcs_get_task_and_bind, null, "oi", [ tcs, gc_handle + 1 ]);
525                         js_obj.__mono_gchandle__ = task_gchandle;
526                         this.mono_wasm_object_registry[gc_handle] = js_obj;
527                         this.free_task_completion_source(tcs);
528                         tcs.is_mono_tcs_task_bound = true;
529                         js_obj.__mono_bound_tcs__ = tcs.__mono_gchandle__;
530                         tcs.__mono_bound_task__ = js_obj.__mono_gchandle__;
531                         return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
532                 },
534                 free_task_completion_source: function (tcs) {
535                         if (tcs.is_mono_tcs_result_set)
536                         {
537                                 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_gchandle__ ]);
538                         }
539                         if (tcs.__mono_bound_task__)
540                         {
541                                 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_bound_task__ ]);
542                         }
543                 },
545                 extract_mono_obj: function (js_obj) {
547                         if (js_obj === null || typeof js_obj === "undefined")
548                                 return 0;
550                         if (!js_obj.is_mono_bridged_obj) {
551                                 var gc_handle = this.mono_wasm_register_obj(js_obj);
552                                 return this.wasm_get_raw_obj (gc_handle);
553                         }
556                         return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
557                 },
559                 extract_js_obj: function (mono_obj) {
560                         if (mono_obj == 0)
561                                 return null;
563                         var js_id = this.wasm_get_js_id (mono_obj);
564                         if (js_id > 0)
565                                 return this.mono_wasm_require_handle(js_id);
567                         var gcHandle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
568                         var js_obj = {
569                                 __mono_gchandle__: this.wasm_bind_existing(mono_obj, gcHandle + 1),
570                                 is_mono_bridged_obj: true
571                         };
573                         this.mono_wasm_object_registry[gcHandle] = js_obj;
574                         return js_obj;
575                 },
577                 /*
578                 args_marshal is a string with one character per parameter that tells how to marshal it, here are the valid values:
580                 i: int32
581                 j: int32 - Enum with underlying type of int32
582                 l: int64 
583                 k: int64 - Enum with underlying type of int64
584                 f: float
585                 d: double
586                 s: string
587                 o: js object will be converted to a C# object (this will box numbers/bool/promises)
588                 m: raw mono object. Don't use it unless you know what you're doing
590                 additionally you can append 'm' to args_marshal beyond `args.length` if you don't want the return value marshaled
591                 */
592                 call_method: function (method, this_arg, args_marshal, args) {
593                         this.bindings_lazy_init ();
595                         var extra_args_mem = 0;
596                         for (var i = 0; i < args.length; ++i) {
597                                 //long/double memory must be 8 bytes aligned and I'm being lazy here
598                                 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')
599                                         extra_args_mem += 8;
600                         }
602                         var extra_args_mem = extra_args_mem ? Module._malloc (extra_args_mem) : 0;
603                         var extra_arg_idx = 0;
604                         var args_mem = Module._malloc (args.length * 4);
605                         var eh_throw = Module._malloc (4);
606                         for (var i = 0; i < args.length; ++i) {
607                                 if (args_marshal[i] == 's') {
608                                         Module.setValue (args_mem + i * 4, this.js_string_to_mono_string (args [i]), "i32");
609                                 } else if (args_marshal[i] == 'm') {
610                                         Module.setValue (args_mem + i * 4, args [i], "i32");
611                                 } else if (args_marshal[i] == 'o') {
612                                         Module.setValue (args_mem + i * 4, this.js_to_mono_obj (args [i]), "i32");
613                                 } else if (args_marshal[i] == 'j'  || args_marshal[i] == 'k') {
614                                         var enumVal = this.js_to_mono_enum(method, i, args[i]);
615                 
616                                         var extra_cell = extra_args_mem + extra_arg_idx;
617                                         extra_arg_idx += 8;
619                                         if (args_marshal[i] == 'j')
620                                                 Module.setValue (extra_cell, enumVal, "i32");
621                                         else if (args_marshal[i] == 'k')
622                                                 Module.setValue (extra_cell, enumVal, "i64");
624                                         Module.setValue (args_mem + i * 4, extra_cell, "i32");
625                                 } else if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd') {
626                                         var extra_cell = extra_args_mem + extra_arg_idx;
627                                         extra_arg_idx += 8;
629                                         if (args_marshal[i] == 'i')
630                                                 Module.setValue (extra_cell, args [i], "i32");
631                                         else if (args_marshal[i] == 'l')
632                                                 Module.setValue (extra_cell, args [i], "i64");
633                                         else if (args_marshal[i] == 'f')
634                                                 Module.setValue (extra_cell, args [i], "float");
635                                         else
636                                                 Module.setValue (extra_cell, args [i], "double");
638                                         Module.setValue (args_mem + i * 4, extra_cell, "i32");
639                                 }
640                         }
641                         Module.setValue (eh_throw, 0, "i32");
643                         var res = this.invoke_method (method, this_arg, args_mem, eh_throw);
645                         var eh_res = Module.getValue (eh_throw, "i32");
647                         if (extra_args_mem)
648                                 Module._free (extra_args_mem);
649                         Module._free (args_mem);
650                         Module._free (eh_throw);
652                         if (eh_res != 0) {
653                                 var msg = this.conv_string (res);
654                                 throw new Error (msg); //the convention is that invoke_method ToString () any outgoing exception
655                         }
657                         if (args_marshal !== null && typeof args_marshal !== "undefined") 
658                         {
659                                 if (args_marshal.length >= args.length && args_marshal [args.length] === "m")
660                                         return res;
661                         }
663                         return this.unbox_mono_obj (res);
664                 },
666                 invoke_delegate: function (delegate_obj, js_args) {
667                         this.bindings_lazy_init ();
669                         if (!this.delegate_dynamic_invoke) {
670                                 if (!this.corlib)
671                                         this.corlib = this.assembly_load ("mscorlib");
672                                 if (!this.delegate_class)
673                                         this.delegate_class = this.find_class (this.corlib, "System", "Delegate");
674                                 if (!this.delegate_class)
675                                 {
676                                         throw new Error("System.Delegate class can not be resolved.");
677                                 }
678                                 this.delegate_dynamic_invoke = this.find_method (this.delegate_class, "DynamicInvoke", -1);
679                         }
680                         var mono_args = this.js_array_to_mono_array (js_args);
681                         if (!this.delegate_dynamic_invoke)
682                                 throw new Error("System.Delegate.DynamicInvoke method can not be resolved.");
683                         // Note: the single 'm' passed here is causing problems with AOT.  Changed to "mo" again.  
684                         // This may need more analysis if causes problems again.
685                         return this.call_method (this.delegate_dynamic_invoke, this.extract_mono_obj (delegate_obj), "mo", [ mono_args ]);
686                 },
687                 
688                 resolve_method_fqn: function (fqn) {
689                         var assembly = fqn.substring(fqn.indexOf ("[") + 1, fqn.indexOf ("]")).trim();
690                         fqn = fqn.substring (fqn.indexOf ("]") + 1).trim();
692                         var methodname = fqn.substring(fqn.indexOf (":") + 1);
693                         fqn = fqn.substring (0, fqn.indexOf (":")).trim ();
695                         var namespace = "";
696                         var classname = fqn;
697                         if (fqn.indexOf(".") != -1) {
698                                 var idx = fqn.lastIndexOf(".");
699                                 namespace = fqn.substring (0, idx);
700                                 classname = fqn.substring (idx + 1);
701                         }
703                         var asm = this.assembly_load (assembly);
704                         if (!asm)
705                                 throw new Error ("Could not find assembly: " + assembly);
707                         var klass = this.find_class(asm, namespace, classname);
708                         if (!klass)
709                                 throw new Error ("Could not find class: " + namespace + ":" +classname);
711                         var method = this.find_method (klass, methodname, -1);
712                         if (!method)
713                                 throw new Error ("Could not find method: " + methodname);
714                         return method;
715                 },
717                 call_static_method: function (fqn, args, 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 this.call_method (method, null, signature, args);
726                 },
728                 bind_static_method: function (fqn, signature) {
729                         this.bindings_lazy_init ();
731                         var method = this.resolve_method_fqn (fqn);
733                         if (typeof signature === "undefined")
734                                 signature = Module.mono_method_get_call_signature (method);
736                         return function() {
737                                 return BINDING.call_method (method, null, signature, arguments);
738                         };
739                 },
740                 wasm_get_core_type: function (obj)
741                 {
742                         return this.call_method (this.get_core_type, null, "so", [ "WebAssembly.Core."+obj.constructor.name ]);
743                 },
744                 get_wasm_type: function(obj) {
745                         var coreType = obj[Symbol.for("wasm type")];
746                         if (typeof coreType === "undefined") {
747                                 switch (obj.constructor.name) {
748                                         case "Array":
749                                                 coreType = this.wasm_get_core_type(obj);
750                                                 if (typeof coreType !== "undefined") {
751                                                         Array.prototype[Symbol.for("wasm type")] = coreType
752                                                 }
753                                                 break;
754                                         case "ArrayBuffer":
755                                                 coreType = this.wasm_get_core_type(obj);
756                                                 if (typeof coreType !== "undefined") {
757                                                         ArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
758                                                 }
759                                                 break;
760                                         case "Int8Array":
761                                                 coreType = this.wasm_get_core_type(obj);
762                                                 if (typeof coreType !== "undefined") {
763                                                         Int8Array.prototype[Symbol.for("wasm type")] = coreType
764                                                 }
765                                                 break;
766                                         case "Uint8Array":
767                                                 coreType = this.wasm_get_core_type(obj);
768                                                 if (typeof coreType !== "undefined") {
769                                                         Uint8Array.prototype[Symbol.for("wasm type")] = coreType
770                                                 }
771                                                 break;
772                                         case "Uint8ClampedArray":
773                                                 coreType = this.wasm_get_core_type(obj);
774                                                 if (typeof coreType !== "undefined") {
775                                                         Uint8ClampedArray.prototype[Symbol.for("wasm type")] = coreType
776                                                 }
777                                                 break;
778                                         case "Int16Array":
779                                                 coreType = this.wasm_get_core_type(obj);
780                                                 if (typeof coreType !== "undefined") {
781                                                         Int16Array.prototype[Symbol.for("wasm type")] = coreType
782                                                 }
783                                                 break;
784                                         case "Uint16Array":
785                                                 coreType = this.wasm_get_core_type(obj);
786                                                 if (typeof coreType !== "undefined") {
787                                                         Uint16Array.prototype[Symbol.for("wasm type")] = coreType
788                                                 }
789                                                 break;
790                                         case "Int32Array":
791                                                 coreType = this.wasm_get_core_type(obj);
792                                                 if (typeof coreType !== "undefined") {
793                                                         Int32Array.prototype[Symbol.for("wasm type")] = coreType
794                                                 }
795                                                 break;
796                                         case "Uint32Array":
797                                                 coreType = this.wasm_get_core_type(obj);
798                                                 if (typeof coreType !== "undefined") {
799                                                         Uint32Array.prototype[Symbol.for("wasm type")] = coreType
800                                                 }
801                                                 return coreType;
802                                         case "Float32Array":
803                                                 coreType = this.wasm_get_core_type(obj);
804                                                 if (typeof coreType !== "undefined") {
805                                                         Float32Array.prototype[Symbol.for("wasm type")] = coreType
806                                                 }
807                                                 break;
808                                         case "Float64Array":
809                                                 coreType = this.wasm_get_core_type(obj);
810                                                 if (typeof coreType !== "undefined") {
811                                                         Float64Array.prototype[Symbol.for("wasm type")] = coreType
812                                                 }
813                                                 break;
814                                         case "Function":
815                                                 coreType = this.wasm_get_core_type(obj);
816                                                 if (typeof coreType !== "undefined") {
817                                                         Function.prototype[Symbol.for("wasm type")] = coreType
818                                                 }
819                                                 break;
820                                         case "SharedArrayBuffer":
821                                                 coreType = this.wasm_get_core_type(obj);
822                                                 if (typeof coreType !== "undefined") {
823                                                         SharedArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
824                                                 }
825                                                 break;
826                                         case "DataView":
827                                                 coreType = this.wasm_get_core_type(obj);
828                                                 if (typeof coreType !== "undefined") {
829                                                         DataView.prototype[Symbol.for("wasm type")] = coreType
830                                                 }
831                                                 break;
832                                 }
833                         }
834                         return coreType;
835                 },
836                 // Object wrapping helper functions to handle reference handles that will
837                 // be used in managed code.
838                 mono_wasm_register_obj: function(obj) {
840                         var gc_handle = undefined;
841                         if (obj !== null && typeof obj !== "undefined") 
842                         {
843                                 gc_handle = obj.__mono_gchandle__;
845                                 if (typeof gc_handle === "undefined") {
846                                         var handle = this.mono_wasm_free_list.length ?
847                                                                 this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
848                                         obj.__mono_jshandle__ = handle;
849                                         // Obtain the JS -> C# type mapping.
850                                         var wasm_type = this.get_wasm_type(obj);
851                                         gc_handle = obj.__mono_gchandle__ = this.wasm_binding_obj_new(handle + 1, wasm_type);
852                                         this.mono_wasm_object_registry[handle] = obj;
853                                                 
854                                 }
855                         }
856                         return gc_handle;
857                 },
858                 mono_wasm_require_handle: function(handle) {
859                         if (handle > 0)
860                                 return this.mono_wasm_object_registry[handle - 1];
861                         return null;
862                 },
863                 mono_wasm_unregister_obj: function(js_id) {
864                         var obj = this.mono_wasm_object_registry[js_id - 1];
865                         if (typeof obj  !== "undefined" && obj !== null) {
866                                 // if this is the global object then do not
867                                 // unregister it.
868                                 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj)
869                                         return obj;
871                                 var gc_handle = obj.__mono_gchandle__;
872                                 if (typeof gc_handle  !== "undefined") {
873                                         this.wasm_unbind_js_obj_and_free(js_id);
875                                         obj.__mono_gchandle__ = undefined;
876                                         obj.__mono_jshandle__ = undefined;
878                                         this.mono_wasm_object_registry[js_id - 1] = undefined;
879                                         this.mono_wasm_free_list.push(js_id - 1);
880                                 }
881                         }
882                         return obj;
883                 },
884                 mono_wasm_free_handle: function(handle) {
885                         this.mono_wasm_unregister_obj(handle);
886                 },
887                 mono_wasm_free_raw_object: function(js_id) {
888                         var obj = this.mono_wasm_object_registry[js_id - 1];
889                         if (typeof obj  !== "undefined" && obj !== null) {
890                                 // if this is the global object then do not
891                                 // unregister it.
892                                 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj)
893                                         return obj;
895                                 var gc_handle = obj.__mono_gchandle__;
896                                 if (typeof gc_handle  !== "undefined") {
898                                         obj.__mono_gchandle__ = undefined;
899                                         obj.__mono_jshandle__ = undefined;
901                                         this.mono_wasm_object_registry[js_id - 1] = undefined;
902                                         this.mono_wasm_free_list.push(js_id - 1);
903                                 }
904                         }
905                         return obj;
906                 },
907                 mono_wasm_get_global: function() {
908                         function testGlobal(obj) {
909                                 obj['___mono_wasm_global___'] = obj;
910                                 var success = typeof ___mono_wasm_global___ === 'object' && obj['___mono_wasm_global___'] === obj;
911                                 if (!success) {
912                                         delete obj['___mono_wasm_global___'];
913                                 }
914                                 return success;
915                         }
916                         if (typeof ___mono_wasm_global___ === 'object') {
917                                 return ___mono_wasm_global___;
918                         }
919                         if (typeof global === 'object' && testGlobal(global)) {
920                                 ___mono_wasm_global___ = global;
921                         } else if (typeof window === 'object' && testGlobal(window)) {
922                                 ___mono_wasm_global___ = window;
923                         } else if (testGlobal((function(){return Function;})()('return this')())) {
925                                 ___mono_wasm_global___ = (function(){return Function;})()('return this')();
927                         }
928                         if (typeof ___mono_wasm_global___ === 'object') {
929                                 return ___mono_wasm_global___;
930                         }
931                         throw Error('unable to get mono wasm global object.');
932                 },
933         
934         },
936         mono_wasm_invoke_js_with_args: function(js_handle, method_name, args, is_exception) {
937                 BINDING.bindings_lazy_init ();
939                 var obj = BINDING.get_js_obj (js_handle);
940                 if (!obj) {
941                         setValue (is_exception, 1, "i32");
942                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
943                 }
945                 var js_name = BINDING.conv_string (method_name);
946                 if (!js_name) {
947                         setValue (is_exception, 1, "i32");
948                         return BINDING.js_string_to_mono_string ("Invalid method name object '" + method_name + "'");
949                 }
951                 var js_args = BINDING.mono_array_to_js_array(args);
953                 var res;
954                 try {
955                         var m = obj [js_name];
956                         if (typeof m === "undefined")
957                                 throw new Error("Method: '" + js_name + "' not found for: '" + Object.prototype.toString.call(obj) + "'");
958                         var res = m.apply (obj, js_args);
959                         return BINDING.js_to_mono_obj (res);
960                 } catch (e) {
961                         var res = e.toString ();
962                         setValue (is_exception, 1, "i32");
963                         if (res === null || res === undefined)
964                                 res = "unknown exception";
965                         return BINDING.js_string_to_mono_string (res);
966                 }
967         },
968         mono_wasm_get_object_property: function(js_handle, property_name, is_exception) {
969                 BINDING.bindings_lazy_init ();
971                 var obj = BINDING.mono_wasm_require_handle (js_handle);
972                 if (!obj) {
973                         setValue (is_exception, 1, "i32");
974                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
975                 }
977                 var js_name = BINDING.conv_string (property_name);
978                 if (!js_name) {
979                         setValue (is_exception, 1, "i32");
980                         return BINDING.js_string_to_mono_string ("Invalid property name object '" + js_name + "'");
981                 }
983                 var res;
984                 try {
985                         var m = obj [js_name];
986                         if (m === Object(m) && obj.__is_mono_proxied__)
987                                 m.__is_mono_proxied__ = true;
988                                 
989                         return BINDING.js_to_mono_obj (m);
990                 } catch (e) {
991                         var res = e.toString ();
992                         setValue (is_exception, 1, "i32");
993                         if (res === null || typeof res === "undefined")
994                                 res = "unknown exception";
995                         return BINDING.js_string_to_mono_string (res);
996                 }
997         },
998     mono_wasm_set_object_property: function (js_handle, property_name, value, createIfNotExist, hasOwnProperty, is_exception) {
1000                 BINDING.bindings_lazy_init ();
1002                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1003                 if (!requireObject) {
1004                         setValue (is_exception, 1, "i32");
1005                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1006                 }
1008                 var property = BINDING.conv_string (property_name);
1009                 if (!property) {
1010                         setValue (is_exception, 1, "i32");
1011                         return BINDING.js_string_to_mono_string ("Invalid property name object '" + property_name + "'");
1012                 }
1014         var result = false;
1016                 var js_value = BINDING.unbox_mono_obj(value);
1018         if (createIfNotExist) {
1019             requireObject[property] = js_value;
1020             result = true;
1021         }
1022         else {
1023                         result = false;
1024                         if (!createIfNotExist)
1025                         {
1026                                 if (!requireObject.hasOwnProperty(property))
1027                                         return false;
1028                         }
1029             if (hasOwnProperty === true) {
1030                 if (requireObject.hasOwnProperty(property)) {
1031                     requireObject[property] = js_value;
1032                     result = true;
1033                 }
1034             }
1035             else {
1036                 requireObject[property] = js_value;
1037                 result = true;
1038             }
1039         
1040         }
1041         return BINDING.call_method (BINDING.box_js_bool, null, "im", [ result ]);
1042         },
1043         mono_wasm_get_by_index: function(js_handle, property_index, is_exception) {
1044                 BINDING.bindings_lazy_init ();
1046                 var obj = BINDING.mono_wasm_require_handle (js_handle);
1047                 if (!obj) {
1048                         setValue (is_exception, 1, "i32");
1049                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1050                 }
1052                 try {
1053                         var m = obj [property_index];
1054                         return BINDING.js_to_mono_obj (m);
1055                 } catch (e) {
1056                         var res = e.toString ();
1057                         setValue (is_exception, 1, "i32");
1058                         if (res === null || typeof res === "undefined")
1059                                 res = "unknown exception";
1060                         return BINDING.js_string_to_mono_string (res);
1061                 }
1062         },
1063         mono_wasm_set_by_index: function(js_handle, property_index, value, is_exception) {
1064                 BINDING.bindings_lazy_init ();
1066                 var obj = BINDING.mono_wasm_require_handle (js_handle);
1067                 if (!obj) {
1068                         setValue (is_exception, 1, "i32");
1069                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1070                 }
1072                 var js_value = BINDING.unbox_mono_obj(value);
1074                 try {
1075                         obj [property_index] = js_value;
1076                         return true;
1077                 } catch (e) {
1078                         var res = e.toString ();
1079                         setValue (is_exception, 1, "i32");
1080                         if (res === null || typeof res === "undefined")
1081                                 res = "unknown exception";
1082                         return BINDING.js_string_to_mono_string (res);
1083                 }
1084         },
1085         mono_wasm_get_global_object: function(global_name, is_exception) {
1086                 BINDING.bindings_lazy_init ();
1088                 var js_name = BINDING.conv_string (global_name);
1090                 var globalObj = undefined;
1092                 if (!js_name) {
1093                         globalObj = BINDING.mono_wasm_get_global();
1094                 }
1095                 else {
1096                         globalObj = BINDING.mono_wasm_get_global()[js_name];
1097                 }
1099                 if (globalObj === null || typeof globalObj === undefined) {
1100                         setValue (is_exception, 1, "i32");
1101                         return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found.");
1102                 }
1104                 return BINDING.js_to_mono_obj (globalObj);
1105         },
1106         mono_wasm_release_handle: function(js_handle, is_exception) {
1107                 BINDING.bindings_lazy_init ();
1109                 BINDING.mono_wasm_free_handle(js_handle);
1110         },      
1111         mono_wasm_release_object: function(js_handle, is_exception) {
1112                 BINDING.bindings_lazy_init ();
1114                 BINDING.mono_wasm_free_raw_object(js_handle);
1115         },      
1116         mono_wasm_bind_core_object: function(js_handle, gc_handle, is_exception) {
1117                 BINDING.bindings_lazy_init ();
1119                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1120                 if (!requireObject) {
1121                         setValue (is_exception, 1, "i32");
1122                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1123                 }
1125                 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1126                 requireObject.__mono_gchandle__ = gc_handle;
1127                 return gc_handle;
1128         },
1129         mono_wasm_bind_host_object: function(js_handle, gc_handle, is_exception) {
1130                 BINDING.bindings_lazy_init ();
1132                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1133                 if (!requireObject) {
1134                         setValue (is_exception, 1, "i32");
1135                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1136                 }
1138                 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1139                 requireObject.__mono_gchandle__ = gc_handle;
1140                 return gc_handle;
1141         },
1142         mono_wasm_new: function (core_name, args, is_exception) {
1143                 BINDING.bindings_lazy_init ();
1145                 var js_name = BINDING.conv_string (core_name);
1147                 if (!js_name) {
1148                         setValue (is_exception, 1, "i32");
1149                         return BINDING.js_string_to_mono_string ("Core object '" + js_name + "' not found.");
1150                 }
1152                 var coreObj = BINDING.mono_wasm_get_global()[js_name];
1154                 if (coreObj === null || typeof coreObj === undefined) {
1155                         setValue (is_exception, 1, "i32");
1156                         return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found.");
1157                 }
1159                 var js_args = BINDING.mono_array_to_js_array(args);
1160                 
1161                 try {
1162                         
1163                         // This is all experimental !!!!!!
1164                         var allocator = function(constructor, js_args) {
1165                                 // Not sure if we should be checking for anything here
1166                                 var argsList = new Array();
1167                                 argsList[0] = constructor;
1168                                 if (js_args)
1169                                         argsList = argsList.concat(js_args);
1170                                 var obj = new (constructor.bind.apply(constructor, argsList ));
1171                                 return obj;
1172                         };
1173         
1174                         var res = allocator(coreObj, js_args);
1175                         var gc_handle = BINDING.mono_wasm_free_list.length ? BINDING.mono_wasm_free_list.pop() : BINDING.mono_wasm_ref_counter++;
1176                         BINDING.mono_wasm_object_registry[gc_handle] = res;
1177                         return BINDING.js_to_mono_obj (gc_handle + 1);
1178                 } catch (e) {
1179                         var res = e.toString ();
1180                         setValue (is_exception, 1, "i32");
1181                         if (res === null || res === undefined)
1182                                 res = "Error allocating object.";
1183                         return BINDING.js_string_to_mono_string (res);
1184                 }       
1186         },
1187         mono_wasm_new_object: function(object_handle_or_function, args, is_exception) {
1188                 BINDING.bindings_lazy_init ();
1190                 if (!object_handle_or_function) {
1191                         return BINDING.js_to_mono_obj ({});
1192                 }
1193                 else {
1195                         var requireObject;
1196                         if (typeof object_handle_or_function === 'function')
1197                                 requireObject = object_handle_or_function;
1198                         else
1199                                 requireObject = BINDING.mono_wasm_require_handle (object_handle_or_function);
1201                         if (!requireObject) {
1202                                 setValue (is_exception, 1, "i32");
1203                                 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + object_handle_or_function + "'");
1204                         }
1206                         var js_args = BINDING.mono_array_to_js_array(args);
1207                         
1208                         try {
1209                                 
1210                                 // This is all experimental !!!!!!
1211                                 var allocator = function(constructor, js_args) {
1212                                         // Not sure if we should be checking for anything here
1213                                         var argsList = new Array();
1214                                         argsList[0] = constructor;
1215                                         if (js_args)
1216                                                 argsList = argsList.concat(js_args);
1217                                         var obj = new (constructor.bind.apply(constructor, argsList ));
1218                                         return obj;
1219                                 };
1220                 
1221                                 var res = allocator(requireObject, js_args);
1222                                 return BINDING.extract_mono_obj (res);
1223                         } catch (e) {
1224                                 var res = e.toString ();
1225                                 setValue (is_exception, 1, "i32");
1226                                 if (res === null || res === undefined)
1227                                         res = "Error allocating object.";
1228                                 return BINDING.js_string_to_mono_string (res);
1229                         }       
1230                 }
1232         },
1233         mono_wasm_typed_array_to_array: function(js_handle, is_exception) {
1234                 BINDING.bindings_lazy_init ();
1236                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1237                 if (!requireObject) {
1238                         setValue (is_exception, 1, "i32");
1239                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1240                 }
1242                 return BINDING.js_typed_array_to_array(requireObject);
1243         },
1244         mono_wasm_typed_array_copy_to: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) {
1245                 BINDING.bindings_lazy_init ();
1247                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1248                 if (!requireObject) {
1249                         setValue (is_exception, 1, "i32");
1250                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1251                 }
1253                 var res = BINDING.typedarray_copy_to(requireObject, pinned_array, begin, end, bytes_per_element);
1254                 return BINDING.js_to_mono_obj (res)
1255         },
1256         mono_wasm_typed_array_from: function(pinned_array, begin, end, bytes_per_element, type, is_exception) {
1257                 BINDING.bindings_lazy_init ();
1258                 var res = BINDING.typed_array_from(pinned_array, begin, end, bytes_per_element, type);
1259                 return BINDING.js_to_mono_obj (res)
1260         },
1261         mono_wasm_typed_array_copy_from: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) {
1262                 BINDING.bindings_lazy_init ();
1264                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1265                 if (!requireObject) {
1266                         setValue (is_exception, 1, "i32");
1267                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1268                 }
1270                 var res = BINDING.typedarray_copy_from(requireObject, pinned_array, begin, end, bytes_per_element);
1271                 return BINDING.js_to_mono_obj (res)
1272         },
1277 autoAddDeps(BindingSupportLib, '$BINDING')
1278 mergeInto(LibraryManager.library, BindingSupportLib)