2 var BindingSupportLib = {
3 $BINDING__postset: 'BINDING.export_functions (Module);',
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;
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);
23 bindings_lazy_init: function () {
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();
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")
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);
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)
70 throw "Can't find method " + namespace + "." + classname + ":" + method_name;
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");
103 get_js_obj: function (js_handle) {
105 return this.mono_wasm_require_handle(js_handle);
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) {
114 var raw = this.mono_string_get_utf8 (mono_obj);
115 var res = Module.UTF8ToString (raw);
121 is_nested_array: function (ele) {
122 return this.call_method (this.is_simple_array, null, "mi", [ ele ]);
125 mono_array_to_js_array: function (mono_array) {
130 var len = this.mono_array_length (mono_array);
131 for (var i = 0; i < len; ++i)
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));
137 res.push (this.unbox_mono_obj (ele));
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]));
151 unbox_mono_obj: function (mono_obj) {
154 var type = this.mono_get_obj_type (mono_obj);
155 //See MARSHAL_TYPE_ defines in driver.c
158 return this.mono_unbox_int (mono_obj);
160 return this.mono_unbox_float (mono_obj);
162 return this.conv_string (mono_obj);
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);
168 return BINDING.invoke_delegate (obj, arguments);
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);
178 var promise = new Promise (function (resolve, reject) {
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__;
192 return this.extract_js_obj (mono_obj);
195 return this.mono_unbox_int (mono_obj) != 0;
199 if(this.mono_wasm_marshal_enum_as_int)
201 return this.mono_unbox_enum (mono_obj);
205 enumValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]);
220 throw new Error ("Marshalling of primitive arrays are not supported. Use the corresponding TypedArray instead.");
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;
229 throw new Error ("no idea on how to unbox object kind " + type);
233 create_task_completion_source: function () {
234 return this.call_method (this.create_tcs, null, "i", [ -1 ]);
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);
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);
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));
259 js_to_mono_obj: function (js_obj) {
260 this.bindings_lazy_init ();
262 if (js_obj == null || js_obj == undefined)
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 ]);
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);
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);
287 return this.get_task_and_bind (tcs, js_obj);
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);
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))
309 if (js_obj instanceof Int8Array)
311 if (js_obj instanceof Uint8Array)
313 if (js_obj instanceof Uint8ClampedArray)
315 if (js_obj instanceof Int16Array)
317 if (js_obj instanceof Uint16Array)
319 if (js_obj instanceof Int32Array)
321 if (js_obj instanceof Uint32Array)
323 if (js_obj instanceof Float32Array)
325 if (js_obj instanceof Float64Array)
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);
334 throw new Error("Object '" + js_obj + "' is not a typed array");
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))
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));
378 throw new Error("Object '" + typed_array + "' is not a typed array");
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))
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));
419 throw new Error("Object '" + typed_array + "' is not a typed array");
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) {
428 var newTypedArray = 0;
433 newTypedArray = new Int8Array(end - begin);
436 newTypedArray = new Uint8Array(end - begin);
439 newTypedArray = new Int16Array(end - begin);
442 newTypedArray = new Uint16Array(end - begin);
445 newTypedArray = new Int32Array(end - begin);
448 newTypedArray = new Uint32Array(end - begin);
451 newTypedArray = new Float32Array(end - begin);
454 newTypedArray = new Float64Array(end - begin);
456 case 15: // This is a special case because the typed array is also byte[]
457 newTypedArray = new Uint8ClampedArray(end - begin);
461 this.typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element);
462 return newTypedArray;
464 js_to_mono_enum: function (method, parmIdx, js_obj) {
465 this.bindings_lazy_init ();
467 if (js_obj === null || typeof js_obj === "undefined")
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);
476 wasm_binding_obj_new: function (js_obj_id, type)
478 return this.call_method (this.bind_js_obj, null, "io", [js_obj_id, type]);
480 wasm_bind_existing: function (mono_obj, js_id)
482 return this.call_method (this.bind_existing_obj, null, "mi", [mono_obj, js_id]);
485 wasm_bind_core_clr_obj: function (js_id, gc_handle)
487 return this.call_method (this.bind_core_clr_obj, null, "ii", [js_id, gc_handle]);
490 wasm_unbind_js_obj: function (js_obj_id)
492 this.call_method (this.unbind_js_obj, null, "i", [js_obj_id]);
495 wasm_unbind_js_obj_and_free: function (js_obj_id)
497 this.call_method (this.unbind_js_obj_and_free, null, "i", [js_obj_id]);
500 wasm_get_js_id: function (mono_obj)
502 return this.call_method (this.get_js_id, null, "m", [mono_obj]);
505 wasm_get_raw_obj: function (gchandle)
507 return this.call_method (this.get_raw_mono_obj, null, "im", [gchandle]);
510 try_extract_mono_obj:function (js_obj) {
511 if (js_obj === null || typeof js_obj === "undefined" || typeof js_obj.__mono_gchandle__ === "undefined")
513 return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
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 ]);
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__);
534 free_task_completion_source: function (tcs) {
535 if (tcs.is_mono_tcs_result_set)
537 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_gchandle__ ]);
539 if (tcs.__mono_bound_task__)
541 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_bound_task__ ]);
545 extract_mono_obj: function (js_obj) {
547 if (js_obj === null || typeof js_obj === "undefined")
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);
556 return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
559 extract_js_obj: function (mono_obj) {
563 var js_id = this.wasm_get_js_id (mono_obj);
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++;
569 __mono_gchandle__: this.wasm_bind_existing(mono_obj, gcHandle + 1),
570 is_mono_bridged_obj: true
573 this.mono_wasm_object_registry[gcHandle] = js_obj;
578 args_marshal is a string with one character per parameter that tells how to marshal it, here are the valid values:
581 j: int32 - Enum with underlying type of int32
583 k: int64 - Enum with underlying type of int64
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
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')
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]);
616 var extra_cell = extra_args_mem + extra_arg_idx;
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;
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");
636 Module.setValue (extra_cell, args [i], "double");
638 Module.setValue (args_mem + i * 4, extra_cell, "i32");
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");
648 Module._free (extra_args_mem);
649 Module._free (args_mem);
650 Module._free (eh_throw);
653 var msg = this.conv_string (res);
654 throw new Error (msg); //the convention is that invoke_method ToString () any outgoing exception
657 if (args_marshal !== null && typeof args_marshal !== "undefined")
659 if (args_marshal.length >= args.length && args_marshal [args.length] === "m")
663 return this.unbox_mono_obj (res);
666 invoke_delegate: function (delegate_obj, js_args) {
667 this.bindings_lazy_init ();
669 if (!this.delegate_dynamic_invoke) {
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)
676 throw new Error("System.Delegate class can not be resolved.");
678 this.delegate_dynamic_invoke = this.find_method (this.delegate_class, "DynamicInvoke", -1);
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 ]);
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 ();
697 if (fqn.indexOf(".") != -1) {
698 var idx = fqn.lastIndexOf(".");
699 namespace = fqn.substring (0, idx);
700 classname = fqn.substring (idx + 1);
703 var asm = this.assembly_load (assembly);
705 throw new Error ("Could not find assembly: " + assembly);
707 var klass = this.find_class(asm, namespace, classname);
709 throw new Error ("Could not find class: " + namespace + ":" +classname);
711 var method = this.find_method (klass, methodname, -1);
713 throw new Error ("Could not find method: " + methodname);
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);
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);
737 return BINDING.call_method (method, null, signature, arguments);
740 wasm_get_core_type: function (obj)
742 return this.call_method (this.get_core_type, null, "so", [ "WebAssembly.Core."+obj.constructor.name ]);
744 get_wasm_type: function(obj) {
745 var coreType = obj[Symbol.for("wasm type")];
746 if (typeof coreType === "undefined") {
747 switch (obj.constructor.name) {
749 coreType = this.wasm_get_core_type(obj);
750 if (typeof coreType !== "undefined") {
751 Array.prototype[Symbol.for("wasm type")] = coreType
755 coreType = this.wasm_get_core_type(obj);
756 if (typeof coreType !== "undefined") {
757 ArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
761 coreType = this.wasm_get_core_type(obj);
762 if (typeof coreType !== "undefined") {
763 Int8Array.prototype[Symbol.for("wasm type")] = coreType
767 coreType = this.wasm_get_core_type(obj);
768 if (typeof coreType !== "undefined") {
769 Uint8Array.prototype[Symbol.for("wasm type")] = coreType
772 case "Uint8ClampedArray":
773 coreType = this.wasm_get_core_type(obj);
774 if (typeof coreType !== "undefined") {
775 Uint8ClampedArray.prototype[Symbol.for("wasm type")] = coreType
779 coreType = this.wasm_get_core_type(obj);
780 if (typeof coreType !== "undefined") {
781 Int16Array.prototype[Symbol.for("wasm type")] = coreType
785 coreType = this.wasm_get_core_type(obj);
786 if (typeof coreType !== "undefined") {
787 Uint16Array.prototype[Symbol.for("wasm type")] = coreType
791 coreType = this.wasm_get_core_type(obj);
792 if (typeof coreType !== "undefined") {
793 Int32Array.prototype[Symbol.for("wasm type")] = coreType
797 coreType = this.wasm_get_core_type(obj);
798 if (typeof coreType !== "undefined") {
799 Uint32Array.prototype[Symbol.for("wasm type")] = coreType
803 coreType = this.wasm_get_core_type(obj);
804 if (typeof coreType !== "undefined") {
805 Float32Array.prototype[Symbol.for("wasm type")] = coreType
809 coreType = this.wasm_get_core_type(obj);
810 if (typeof coreType !== "undefined") {
811 Float64Array.prototype[Symbol.for("wasm type")] = coreType
815 coreType = this.wasm_get_core_type(obj);
816 if (typeof coreType !== "undefined") {
817 Function.prototype[Symbol.for("wasm type")] = coreType
820 case "SharedArrayBuffer":
821 coreType = this.wasm_get_core_type(obj);
822 if (typeof coreType !== "undefined") {
823 SharedArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
827 coreType = this.wasm_get_core_type(obj);
828 if (typeof coreType !== "undefined") {
829 DataView.prototype[Symbol.for("wasm type")] = coreType
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")
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;
858 mono_wasm_require_handle: function(handle) {
860 return this.mono_wasm_object_registry[handle - 1];
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
868 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === 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);
884 mono_wasm_free_handle: function(handle) {
885 this.mono_wasm_unregister_obj(handle);
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
892 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === 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);
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;
912 delete obj['___mono_wasm_global___'];
916 if (typeof ___mono_wasm_global___ === 'object') {
917 return ___mono_wasm_global___;
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')();
928 if (typeof ___mono_wasm_global___ === 'object') {
929 return ___mono_wasm_global___;
931 throw Error('unable to get mono wasm global object.');
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);
941 setValue (is_exception, 1, "i32");
942 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
945 var js_name = BINDING.conv_string (method_name);
947 setValue (is_exception, 1, "i32");
948 return BINDING.js_string_to_mono_string ("Invalid method name object '" + method_name + "'");
951 var js_args = BINDING.mono_array_to_js_array(args);
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);
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);
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);
973 setValue (is_exception, 1, "i32");
974 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
977 var js_name = BINDING.conv_string (property_name);
979 setValue (is_exception, 1, "i32");
980 return BINDING.js_string_to_mono_string ("Invalid property name object '" + js_name + "'");
985 var m = obj [js_name];
986 if (m === Object(m) && obj.__is_mono_proxied__)
987 m.__is_mono_proxied__ = true;
989 return BINDING.js_to_mono_obj (m);
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);
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 + "'");
1008 var property = BINDING.conv_string (property_name);
1010 setValue (is_exception, 1, "i32");
1011 return BINDING.js_string_to_mono_string ("Invalid property name object '" + property_name + "'");
1016 var js_value = BINDING.unbox_mono_obj(value);
1018 if (createIfNotExist) {
1019 requireObject[property] = js_value;
1024 if (!createIfNotExist)
1026 if (!requireObject.hasOwnProperty(property))
1029 if (hasOwnProperty === true) {
1030 if (requireObject.hasOwnProperty(property)) {
1031 requireObject[property] = js_value;
1036 requireObject[property] = js_value;
1041 return BINDING.call_method (BINDING.box_js_bool, null, "im", [ result ]);
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);
1048 setValue (is_exception, 1, "i32");
1049 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1053 var m = obj [property_index];
1054 return BINDING.js_to_mono_obj (m);
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);
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);
1068 setValue (is_exception, 1, "i32");
1069 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1072 var js_value = BINDING.unbox_mono_obj(value);
1075 obj [property_index] = js_value;
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);
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;
1093 globalObj = BINDING.mono_wasm_get_global();
1096 globalObj = BINDING.mono_wasm_get_global()[js_name];
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.");
1104 return BINDING.js_to_mono_obj (globalObj);
1106 mono_wasm_release_handle: function(js_handle, is_exception) {
1107 BINDING.bindings_lazy_init ();
1109 BINDING.mono_wasm_free_handle(js_handle);
1111 mono_wasm_release_object: function(js_handle, is_exception) {
1112 BINDING.bindings_lazy_init ();
1114 BINDING.mono_wasm_free_raw_object(js_handle);
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 + "'");
1125 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1126 requireObject.__mono_gchandle__ = gc_handle;
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 + "'");
1138 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1139 requireObject.__mono_gchandle__ = gc_handle;
1142 mono_wasm_new: function (core_name, args, is_exception) {
1144 var js_name = BINDING.conv_string (core_name);
1147 setValue (is_exception, 1, "i32");
1148 return BINDING.js_string_to_mono_string ("Core object '" + js_name + "' not found.");
1151 var coreObj = BINDING.mono_wasm_get_global()[js_name];
1153 if (coreObj === null || typeof coreObj === undefined) {
1154 setValue (is_exception, 1, "i32");
1155 return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found.");
1158 var js_args = BINDING.mono_array_to_js_array(args);
1162 // This is all experimental !!!!!!
1163 var allocator = function(constructor, js_args) {
1164 // Not sure if we should be checking for anything here
1165 var argsList = new Array();
1166 argsList[0] = constructor;
1168 argsList = argsList.concat(js_args);
1169 var obj = new (constructor.bind.apply(constructor, argsList ));
1173 var res = allocator(coreObj, js_args);
1174 var gc_handle = BINDING.mono_wasm_free_list.length ? BINDING.mono_wasm_free_list.pop() : BINDING.mono_wasm_ref_counter++;
1175 BINDING.mono_wasm_object_registry[gc_handle] = res;
1176 return BINDING.js_to_mono_obj (gc_handle + 1);
1178 var res = e.toString ();
1179 setValue (is_exception, 1, "i32");
1180 if (res === null || res === undefined)
1181 res = "Error allocating object.";
1182 return BINDING.js_string_to_mono_string (res);
1186 mono_wasm_new_object: function(object_handle_or_function, args, is_exception) {
1187 BINDING.bindings_lazy_init ();
1189 if (!object_handle_or_function) {
1190 return BINDING.js_to_mono_obj ({});
1195 if (typeof object_handle_or_function === 'function')
1196 requireObject = object_handle_or_function;
1198 requireObject = BINDING.mono_wasm_require_handle (object_handle_or_function);
1200 if (!requireObject) {
1201 setValue (is_exception, 1, "i32");
1202 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + object_handle_or_function + "'");
1205 var js_args = BINDING.mono_array_to_js_array(args);
1209 // This is all experimental !!!!!!
1210 var allocator = function(constructor, js_args) {
1211 // Not sure if we should be checking for anything here
1212 var argsList = new Array();
1213 argsList[0] = constructor;
1215 argsList = argsList.concat(js_args);
1216 var obj = new (constructor.bind.apply(constructor, argsList ));
1220 var res = allocator(requireObject, js_args);
1221 return BINDING.extract_mono_obj (res);
1223 var res = e.toString ();
1224 setValue (is_exception, 1, "i32");
1225 if (res === null || res === undefined)
1226 res = "Error allocating object.";
1227 return BINDING.js_string_to_mono_string (res);
1232 mono_wasm_typed_array_to_array: function(js_handle, is_exception) {
1233 BINDING.bindings_lazy_init ();
1235 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1236 if (!requireObject) {
1237 setValue (is_exception, 1, "i32");
1238 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1241 return BINDING.js_typed_array_to_array(requireObject);
1243 mono_wasm_typed_array_copy_to: 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 + "'");
1252 var res = BINDING.typedarray_copy_to(requireObject, pinned_array, begin, end, bytes_per_element);
1253 return BINDING.js_to_mono_obj (res)
1255 mono_wasm_typed_array_from: function(pinned_array, begin, end, bytes_per_element, type, is_exception) {
1256 BINDING.bindings_lazy_init ();
1257 var res = BINDING.typed_array_from(pinned_array, begin, end, bytes_per_element, type);
1258 return BINDING.js_to_mono_obj (res)
1260 mono_wasm_typed_array_copy_from: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) {
1261 BINDING.bindings_lazy_init ();
1263 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1264 if (!requireObject) {
1265 setValue (is_exception, 1, "i32");
1266 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1269 var res = BINDING.typedarray_copy_from(requireObject, pinned_array, begin, end, bytes_per_element);
1270 return BINDING.js_to_mono_obj (res)
1276 autoAddDeps(BindingSupportLib, '$BINDING')
1277 mergeInto(LibraryManager.library, BindingSupportLib)