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");
97 this.object_to_enum = get_method ("ObjectToEnum");
101 get_js_obj: function (js_handle) {
103 return this.mono_wasm_require_handle(js_handle);
107 //FIXME this is wastefull, we could remove the temp malloc by going the UTF16 route
108 //FIXME this is unsafe, cuz raw objects could be GC'd.
109 conv_string: function (mono_obj) {
112 var raw = this.mono_string_get_utf8 (mono_obj);
113 var res = Module.UTF8ToString (raw);
119 is_nested_array: function (ele) {
120 return this.call_method (this.is_simple_array, null, "mi", [ ele ]);
123 mono_array_to_js_array: function (mono_array) {
128 var len = this.mono_array_length (mono_array);
129 for (var i = 0; i < len; ++i)
131 var ele = this.mono_array_get (mono_array, i);
132 if (this.is_nested_array(ele))
133 res.push(this.mono_array_to_js_array(ele));
135 res.push (this.unbox_mono_obj (ele));
141 js_array_to_mono_array: function (js_array) {
142 var mono_array = this.mono_obj_array_new (js_array.length);
143 for (var i = 0; i < js_array.length; ++i) {
144 this.mono_obj_array_set (mono_array, i, this.js_to_mono_obj (js_array [i]));
149 unbox_mono_obj: function (mono_obj) {
152 var type = this.mono_get_obj_type (mono_obj);
153 //See MARSHAL_TYPE_ defines in driver.c
156 return this.mono_unbox_int (mono_obj);
158 return this.mono_unbox_float (mono_obj);
160 return this.conv_string (mono_obj);
162 throw new Error ("no idea on how to unbox value types");
163 case 5: { // delegate
164 var obj = this.extract_js_obj (mono_obj);
166 return BINDING.invoke_delegate (obj, arguments);
171 if (typeof Promise === "undefined" || typeof Promise.resolve === "undefined")
172 throw new Error ("Promises are not supported thus C# Tasks can not work in this context.");
174 var obj = this.extract_js_obj (mono_obj);
176 var promise = new Promise (function (resolve, reject) {
183 this.call_method (this.setup_js_cont, null, "mo", [ mono_obj, cont_obj ]);
184 obj.__mono_js_cont__ = cont_obj.__mono_gchandle__;
185 cont_obj.__mono_js_task__ = obj.__mono_gchandle__;
190 return this.extract_js_obj (mono_obj);
193 return this.mono_unbox_int (mono_obj) != 0;
197 if(this.mono_wasm_marshal_enum_as_int)
199 return this.mono_unbox_enum (mono_obj);
203 enumValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]);
218 throw new Error ("Marshalling of primitive arrays are not supported. Use the corresponding TypedArray instead.");
222 throw new Error ("no idea on how to unbox object kind " + type);
226 create_task_completion_source: function () {
227 return this.call_method (this.create_tcs, null, "i", [ -1 ]);
230 set_task_result: function (tcs, result) {
231 tcs.is_mono_tcs_result_set = true;
232 this.call_method (this.set_tcs_result, null, "oo", [ tcs, result ]);
233 if (tcs.is_mono_tcs_task_bound)
234 this.free_task_completion_source(tcs);
237 set_task_failure: function (tcs, reason) {
238 tcs.is_mono_tcs_result_set = true;
239 this.call_method (this.set_tcs_failure, null, "os", [ tcs, reason.toString () ]);
240 if (tcs.is_mono_tcs_task_bound)
241 this.free_task_completion_source(tcs);
244 // https://github.com/Planeshifter/emscripten-examples/blob/master/01_PassingArrays/sum_post.js
245 js_typedarray_to_heap: function(typedArray){
246 var numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT;
247 var ptr = Module._malloc(numBytes);
248 var heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes);
249 heapBytes.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, numBytes));
252 js_to_mono_obj: function (js_obj) {
253 this.bindings_lazy_init ();
255 if (js_obj == null || js_obj == undefined)
257 if (typeof js_obj === 'number') {
258 if (parseInt(js_obj) == js_obj)
259 return this.call_method (this.box_js_int, null, "im", [ js_obj ]);
260 return this.call_method (this.box_js_double, null, "dm", [ js_obj ]);
262 if (typeof js_obj === 'string')
263 return this.js_string_to_mono_string (js_obj);
265 if (typeof js_obj === 'boolean')
266 return this.call_method (this.box_js_bool, null, "im", [ js_obj ]);
268 if (Promise.resolve(js_obj) === js_obj) {
269 var the_task = this.try_extract_mono_obj (js_obj);
272 var tcs = this.create_task_completion_source ();
274 js_obj.then (function (result) {
275 BINDING.set_task_result (tcs, result);
276 }, function (reason) {
277 BINDING.set_task_failure (tcs, reason);
280 return this.get_task_and_bind (tcs, js_obj);
283 return this.extract_mono_obj (js_obj);
285 js_typed_array_to_array : function (js_obj) {
287 // JavaScript typed arrays are array-like objects and provide a mechanism for accessing
288 // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays
289 // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
290 // is an object representing a chunk of data; it has no format to speak of, and offers no
291 // mechanism for accessing its contents. In order to access the memory contained in a buffer,
292 // you need to use a view. A view provides a context — that is, a data type, starting offset,
293 // and number of elements — that turns the data into an actual typed array.
294 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
295 if (!!(js_obj.buffer instanceof ArrayBuffer && js_obj.BYTES_PER_ELEMENT))
298 if (js_obj instanceof Int8Array)
300 if (js_obj instanceof Uint8Array)
302 if (js_obj instanceof Uint8ClampedArray)
304 if (js_obj instanceof Int16Array)
306 if (js_obj instanceof Uint16Array)
308 if (js_obj instanceof Int32Array)
310 if (js_obj instanceof Uint32Array)
312 if (js_obj instanceof Float32Array)
314 if (js_obj instanceof Float64Array)
317 var heapBytes = this.js_typedarray_to_heap(js_obj);
318 var bufferArray = this.mono_typed_array_new(heapBytes.byteOffset, js_obj.length, js_obj.BYTES_PER_ELEMENT, arrayType);
319 Module._free(heapBytes.byteOffset);
323 throw new Error("Object '" + js_obj + "' is not a typed array");
328 // Copy the existing typed array to the heap pointed to by the pinned array address
329 // typed array memory -> copy to heap -> address of managed pinned array
330 typedarray_copy_to : function (typed_array, pinned_array, begin, end, bytes_per_element) {
332 // JavaScript typed arrays are array-like objects and provide a mechanism for accessing
333 // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays
334 // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
335 // is an object representing a chunk of data; it has no format to speak of, and offers no
336 // mechanism for accessing its contents. In order to access the memory contained in a buffer,
337 // you need to use a view. A view provides a context — that is, a data type, starting offset,
338 // and number of elements — that turns the data into an actual typed array.
339 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
340 if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT))
342 // Some sanity checks of what is being asked of us
343 // lets play it safe and throw an error here instead of assuming to much.
344 // Better safe than sorry later
345 if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
346 throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
348 // how much space we have to work with
349 var num_of_bytes = (end - begin) * bytes_per_element;
350 // how much typed buffer space are we talking about
351 var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
352 // only use what is needed.
353 if (num_of_bytes > view_bytes)
354 num_of_bytes = view_bytes;
356 // offset index into the view
357 var offset = begin * bytes_per_element;
359 // Create a view over the heap pointed to by the pinned array address
360 var heapBytes = new Uint8Array(Module.HEAPU8.buffer, pinned_array + offset, num_of_bytes);
361 // Copy the bytes of the typed array to the heap.
362 heapBytes.set(new Uint8Array(typed_array.buffer, typed_array.byteOffset, num_of_bytes));
367 throw new Error("Object '" + typed_array + "' is not a typed array");
371 // Copy the pinned array address from pinned_array allocated on the heap to the typed array.
372 // adress of managed pinned array -> copy from heap -> typed array memory
373 typedarray_copy_from : function (typed_array, pinned_array, begin, end, bytes_per_element) {
375 // JavaScript typed arrays are array-like objects and provide a mechanism for accessing
376 // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays
377 // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
378 // is an object representing a chunk of data; it has no format to speak of, and offers no
379 // mechanism for accessing its contents. In order to access the memory contained in a buffer,
380 // you need to use a view. A view provides a context — that is, a data type, starting offset,
381 // and number of elements — that turns the data into an actual typed array.
382 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
383 if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT))
385 // Some sanity checks of what is being asked of us
386 // lets play it safe and throw an error here instead of assuming to much.
387 // Better safe than sorry later
388 if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
389 throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
391 // how much space we have to work with
392 var num_of_bytes = (end - begin) * bytes_per_element;
393 // how much typed buffer space are we talking about
394 var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
395 // only use what is needed.
396 if (num_of_bytes > view_bytes)
397 num_of_bytes = view_bytes;
399 // Create a new view for mapping
400 var typedarrayBytes = new Uint8Array(typed_array.buffer, 0, num_of_bytes);
401 // offset index into the view
402 var offset = begin * bytes_per_element;
403 // Set view bytes to value from HEAPU8
404 typedarrayBytes.set(Module.HEAPU8.subarray(pinned_array + offset, pinned_array + offset + num_of_bytes));
408 throw new Error("Object '" + typed_array + "' is not a typed array");
412 // Creates a new typed array from pinned array address from pinned_array allocated on the heap to the typed array.
413 // adress of managed pinned array -> copy from heap -> typed array memory
414 typed_array_from : function (pinned_array, begin, end, bytes_per_element, type) {
417 var newTypedArray = 0;
422 newTypedArray = new Int8Array(end - begin);
425 newTypedArray = new Uint8Array(end - begin);
428 newTypedArray = new Int16Array(end - begin);
431 newTypedArray = new Uint16Array(end - begin);
434 newTypedArray = new Int32Array(end - begin);
437 newTypedArray = new Uint32Array(end - begin);
440 newTypedArray = new Float32Array(end - begin);
443 newTypedArray = new Float64Array(end - begin);
445 case 15: // This is a special case because the typed array is also byte[]
446 newTypedArray = new Uint8ClampedArray(end - begin);
450 this.typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element);
451 return newTypedArray;
453 js_to_mono_enum: function (method, parmIdx, js_obj) {
454 this.bindings_lazy_init ();
456 if (js_obj === null || typeof js_obj === "undefined")
459 var monoObj = this.js_to_mono_obj(js_obj);
460 // Check enum contract
461 var monoEnum = this.call_method(this.object_to_enum, null, "iimm", [ method, parmIdx, monoObj ])
462 // return the unboxed enum value.
463 return this.mono_unbox_enum(monoEnum);
465 wasm_binding_obj_new: function (js_obj_id, type)
467 return this.call_method (this.bind_js_obj, null, "io", [js_obj_id, type]);
469 wasm_bind_existing: function (mono_obj, js_id)
471 return this.call_method (this.bind_existing_obj, null, "mi", [mono_obj, js_id]);
474 wasm_bind_core_clr_obj: function (js_id, gc_handle)
476 return this.call_method (this.bind_core_clr_obj, null, "ii", [js_id, gc_handle]);
479 wasm_unbind_js_obj: function (js_obj_id)
481 this.call_method (this.unbind_js_obj, null, "i", [js_obj_id]);
484 wasm_unbind_js_obj_and_free: function (js_obj_id)
486 this.call_method (this.unbind_js_obj_and_free, null, "i", [js_obj_id]);
489 wasm_get_js_id: function (mono_obj)
491 return this.call_method (this.get_js_id, null, "m", [mono_obj]);
494 wasm_get_raw_obj: function (gchandle)
496 return this.call_method (this.get_raw_mono_obj, null, "im", [gchandle]);
499 try_extract_mono_obj:function (js_obj) {
500 if (js_obj === null || typeof js_obj === "undefined" || typeof js_obj.__mono_gchandle__ === "undefined")
502 return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
505 mono_method_get_call_signature: function(method) {
506 this.bindings_lazy_init ();
508 return this.call_method (this.get_call_sig, null, "i", [ method ]);
511 get_task_and_bind: function (tcs, js_obj) {
512 var gc_handle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
513 var task_gchandle = this.call_method (this.tcs_get_task_and_bind, null, "oi", [ tcs, gc_handle + 1 ]);
514 js_obj.__mono_gchandle__ = task_gchandle;
515 this.mono_wasm_object_registry[gc_handle] = js_obj;
516 this.free_task_completion_source(tcs);
517 tcs.is_mono_tcs_task_bound = true;
518 js_obj.__mono_bound_tcs__ = tcs.__mono_gchandle__;
519 tcs.__mono_bound_task__ = js_obj.__mono_gchandle__;
520 return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
523 free_task_completion_source: function (tcs) {
524 if (tcs.is_mono_tcs_result_set)
526 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_gchandle__ ]);
528 if (tcs.__mono_bound_task__)
530 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_bound_task__ ]);
534 extract_mono_obj: function (js_obj) {
536 if (js_obj === null || typeof js_obj === "undefined")
539 if (!js_obj.is_mono_bridged_obj) {
540 var gc_handle = this.mono_wasm_register_obj(js_obj);
541 return this.wasm_get_raw_obj (gc_handle);
545 return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
548 extract_js_obj: function (mono_obj) {
552 var js_id = this.wasm_get_js_id (mono_obj);
554 return this.mono_wasm_require_handle(js_id);
556 var gcHandle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
558 __mono_gchandle__: this.wasm_bind_existing(mono_obj, gcHandle + 1),
559 is_mono_bridged_obj: true
562 this.mono_wasm_object_registry[gcHandle] = js_obj;
567 args_marshal is a string with one character per parameter that tells how to marshal it, here are the valid values:
570 j: int32 - Enum with underlying type of int32
572 k: int64 - Enum with underlying type of int64
576 o: js object will be converted to a C# object (this will box numbers/bool/promises)
577 m: raw mono object. Don't use it unless you know what you're doing
579 additionally you can append 'm' to args_marshal beyond `args.length` if you don't want the return value marshaled
581 call_method: function (method, this_arg, args_marshal, args) {
582 this.bindings_lazy_init ();
584 var extra_args_mem = 0;
585 for (var i = 0; i < args.length; ++i) {
586 //long/double memory must be 8 bytes aligned and I'm being lazy here
587 if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd' || args_marshal[i] == 'j' || args_marshal[i] == 'k')
591 var extra_args_mem = extra_args_mem ? Module._malloc (extra_args_mem) : 0;
592 var extra_arg_idx = 0;
593 var args_mem = Module._malloc (args.length * 4);
594 var eh_throw = Module._malloc (4);
595 for (var i = 0; i < args.length; ++i) {
596 if (args_marshal[i] == 's') {
597 Module.setValue (args_mem + i * 4, this.js_string_to_mono_string (args [i]), "i32");
598 } else if (args_marshal[i] == 'm') {
599 Module.setValue (args_mem + i * 4, args [i], "i32");
600 } else if (args_marshal[i] == 'o') {
601 Module.setValue (args_mem + i * 4, this.js_to_mono_obj (args [i]), "i32");
602 } else if (args_marshal[i] == 'j' || args_marshal[i] == 'k') {
603 var enumVal = this.js_to_mono_enum(method, i, args[i]);
605 var extra_cell = extra_args_mem + extra_arg_idx;
608 if (args_marshal[i] == 'j')
609 Module.setValue (extra_cell, enumVal, "i32");
610 else if (args_marshal[i] == 'k')
611 Module.setValue (extra_cell, enumVal, "i64");
613 Module.setValue (args_mem + i * 4, extra_cell, "i32");
614 } else if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd') {
615 var extra_cell = extra_args_mem + extra_arg_idx;
618 if (args_marshal[i] == 'i')
619 Module.setValue (extra_cell, args [i], "i32");
620 else if (args_marshal[i] == 'l')
621 Module.setValue (extra_cell, args [i], "i64");
622 else if (args_marshal[i] == 'f')
623 Module.setValue (extra_cell, args [i], "float");
625 Module.setValue (extra_cell, args [i], "double");
627 Module.setValue (args_mem + i * 4, extra_cell, "i32");
630 Module.setValue (eh_throw, 0, "i32");
632 var res = this.invoke_method (method, this_arg, args_mem, eh_throw);
634 var eh_res = Module.getValue (eh_throw, "i32");
637 Module._free (extra_args_mem);
638 Module._free (args_mem);
639 Module._free (eh_throw);
642 var msg = this.conv_string (res);
643 throw new Error (msg); //the convention is that invoke_method ToString () any outgoing exception
646 if (args_marshal !== null && typeof args_marshal !== "undefined")
648 if (args_marshal.length >= args.length && args_marshal [args.length] === "m")
652 return this.unbox_mono_obj (res);
655 invoke_delegate: function (delegate_obj, js_args) {
656 this.bindings_lazy_init ();
658 if (!this.delegate_dynamic_invoke) {
660 this.corlib = this.assembly_load ("mscorlib");
661 if (!this.delegate_class)
662 this.delegate_class = this.find_class (this.corlib, "System", "Delegate");
663 if (!this.delegate_class)
665 throw new Error("System.Delegate class can not be resolved.");
667 this.delegate_dynamic_invoke = this.find_method (this.delegate_class, "DynamicInvoke", -1);
669 var mono_args = this.js_array_to_mono_array (js_args);
670 if (!this.delegate_dynamic_invoke)
671 throw new Error("System.Delegate.DynamicInvoke method can not be resolved.");
672 // Note: the single 'm' passed here is causing problems with AOT. Changed to "mo" again.
673 // This may need more analysis if causes problems again.
674 return this.call_method (this.delegate_dynamic_invoke, this.extract_mono_obj (delegate_obj), "mo", [ mono_args ]);
677 resolve_method_fqn: function (fqn) {
678 var assembly = fqn.substring(fqn.indexOf ("[") + 1, fqn.indexOf ("]")).trim();
679 fqn = fqn.substring (fqn.indexOf ("]") + 1).trim();
681 var methodname = fqn.substring(fqn.indexOf (":") + 1);
682 fqn = fqn.substring (0, fqn.indexOf (":")).trim ();
686 if (fqn.indexOf(".") != -1) {
687 var idx = fqn.lastIndexOf(".");
688 namespace = fqn.substring (0, idx);
689 classname = fqn.substring (idx + 1);
692 var asm = this.assembly_load (assembly);
694 throw new Error ("Could not find assembly: " + assembly);
696 var klass = this.find_class(asm, namespace, classname);
698 throw new Error ("Could not find class: " + namespace + ":" +classname);
700 var method = this.find_method (klass, methodname, -1);
702 throw new Error ("Could not find method: " + methodname);
706 call_static_method: function (fqn, args, signature) {
707 this.bindings_lazy_init ();
709 var method = this.resolve_method_fqn (fqn);
711 if (typeof signature === "undefined")
712 signature = Module.mono_method_get_call_signature (method);
714 return this.call_method (method, null, signature, args);
717 bind_static_method: function (fqn, signature) {
718 this.bindings_lazy_init ();
720 var method = this.resolve_method_fqn (fqn);
722 if (typeof signature === "undefined")
723 signature = Module.mono_method_get_call_signature (method);
726 return BINDING.call_method (method, null, signature, arguments);
729 wasm_get_core_type: function (obj)
731 return this.call_method (this.get_core_type, null, "so", [ "WebAssembly.Core."+obj.constructor.name ]);
733 get_wasm_type: function(obj) {
734 var coreType = obj[Symbol.for("wasm type")];
735 if (typeof coreType === "undefined") {
736 switch (obj.constructor.name) {
738 coreType = this.wasm_get_core_type(obj);
739 if (typeof coreType !== "undefined") {
740 Array.prototype[Symbol.for("wasm type")] = coreType
744 coreType = this.wasm_get_core_type(obj);
745 if (typeof coreType !== "undefined") {
746 ArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
750 coreType = this.wasm_get_core_type(obj);
751 if (typeof coreType !== "undefined") {
752 Int8Array.prototype[Symbol.for("wasm type")] = coreType
756 coreType = this.wasm_get_core_type(obj);
757 if (typeof coreType !== "undefined") {
758 Uint8Array.prototype[Symbol.for("wasm type")] = coreType
761 case "Uint8ClampedArray":
762 coreType = this.wasm_get_core_type(obj);
763 if (typeof coreType !== "undefined") {
764 Uint8ClampedArray.prototype[Symbol.for("wasm type")] = coreType
768 coreType = this.wasm_get_core_type(obj);
769 if (typeof coreType !== "undefined") {
770 Int16Array.prototype[Symbol.for("wasm type")] = coreType
774 coreType = this.wasm_get_core_type(obj);
775 if (typeof coreType !== "undefined") {
776 Uint16Array.prototype[Symbol.for("wasm type")] = coreType
780 coreType = this.wasm_get_core_type(obj);
781 if (typeof coreType !== "undefined") {
782 Int32Array.prototype[Symbol.for("wasm type")] = coreType
786 coreType = this.wasm_get_core_type(obj);
787 if (typeof coreType !== "undefined") {
788 Uint32Array.prototype[Symbol.for("wasm type")] = coreType
792 coreType = this.wasm_get_core_type(obj);
793 if (typeof coreType !== "undefined") {
794 Float32Array.prototype[Symbol.for("wasm type")] = coreType
798 coreType = this.wasm_get_core_type(obj);
799 if (typeof coreType !== "undefined") {
800 Float64Array.prototype[Symbol.for("wasm type")] = coreType
804 coreType = this.wasm_get_core_type(obj);
805 if (typeof coreType !== "undefined") {
806 Function.prototype[Symbol.for("wasm type")] = coreType
809 case "SharedArrayBuffer":
810 coreType = this.wasm_get_core_type(obj);
811 if (typeof coreType !== "undefined") {
812 SharedArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
819 // Object wrapping helper functions to handle reference handles that will
820 // be used in managed code.
821 mono_wasm_register_obj: function(obj) {
823 var gc_handle = undefined;
824 if (obj !== null && typeof obj !== "undefined")
826 gc_handle = obj.__mono_gchandle__;
828 if (typeof gc_handle === "undefined") {
829 var handle = this.mono_wasm_free_list.length ?
830 this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
831 obj.__mono_jshandle__ = handle;
832 // Obtain the JS -> C# type mapping.
833 var wasm_type = this.get_wasm_type(obj);
834 gc_handle = obj.__mono_gchandle__ = this.wasm_binding_obj_new(handle + 1, wasm_type);
835 this.mono_wasm_object_registry[handle] = obj;
841 mono_wasm_require_handle: function(handle) {
843 return this.mono_wasm_object_registry[handle - 1];
846 mono_wasm_unregister_obj: function(js_id) {
847 var obj = this.mono_wasm_object_registry[js_id - 1];
848 if (typeof obj !== "undefined" && obj !== null) {
849 // if this is the global object then do not
851 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj)
854 var gc_handle = obj.__mono_gchandle__;
855 if (typeof gc_handle !== "undefined") {
856 this.wasm_unbind_js_obj_and_free(js_id);
858 obj.__mono_gchandle__ = undefined;
859 obj.__mono_jshandle__ = undefined;
861 this.mono_wasm_object_registry[js_id - 1] = undefined;
862 this.mono_wasm_free_list.push(js_id - 1);
867 mono_wasm_free_handle: function(handle) {
868 this.mono_wasm_unregister_obj(handle);
870 mono_wasm_free_raw_object: function(js_id) {
871 var obj = this.mono_wasm_object_registry[js_id - 1];
872 if (typeof obj !== "undefined" && obj !== null) {
873 // if this is the global object then do not
875 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj)
878 var gc_handle = obj.__mono_gchandle__;
879 if (typeof gc_handle !== "undefined") {
881 obj.__mono_gchandle__ = undefined;
882 obj.__mono_jshandle__ = undefined;
884 this.mono_wasm_object_registry[js_id - 1] = undefined;
885 this.mono_wasm_free_list.push(js_id - 1);
890 mono_wasm_get_global: function() {
891 function testGlobal(obj) {
892 obj['___mono_wasm_global___'] = obj;
893 var success = typeof ___mono_wasm_global___ === 'object' && obj['___mono_wasm_global___'] === obj;
895 delete obj['___mono_wasm_global___'];
899 if (typeof ___mono_wasm_global___ === 'object') {
900 return ___mono_wasm_global___;
902 if (typeof global === 'object' && testGlobal(global)) {
903 ___mono_wasm_global___ = global;
904 } else if (typeof window === 'object' && testGlobal(window)) {
905 ___mono_wasm_global___ = window;
906 } else if (testGlobal((function(){return Function;})()('return this')())) {
908 ___mono_wasm_global___ = (function(){return Function;})()('return this')();
911 if (typeof ___mono_wasm_global___ === 'object') {
912 return ___mono_wasm_global___;
914 throw Error('unable to get mono wasm global object.');
919 mono_wasm_invoke_js_with_args: function(js_handle, method_name, args, is_exception) {
920 BINDING.bindings_lazy_init ();
922 var obj = BINDING.get_js_obj (js_handle);
924 setValue (is_exception, 1, "i32");
925 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
928 var js_name = BINDING.conv_string (method_name);
930 setValue (is_exception, 1, "i32");
931 return BINDING.js_string_to_mono_string ("Invalid method name object '" + method_name + "'");
934 var js_args = BINDING.mono_array_to_js_array(args);
938 var m = obj [js_name];
939 if (typeof m === "undefined")
940 throw new Error("Method: '" + js_name + "' not found for: '" + Object.prototype.toString.call(obj) + "'");
941 var res = m.apply (obj, js_args);
942 return BINDING.js_to_mono_obj (res);
944 var res = e.toString ();
945 setValue (is_exception, 1, "i32");
946 if (res === null || res === undefined)
947 res = "unknown exception";
948 return BINDING.js_string_to_mono_string (res);
951 mono_wasm_get_object_property: function(js_handle, property_name, is_exception) {
952 BINDING.bindings_lazy_init ();
954 var obj = BINDING.mono_wasm_require_handle (js_handle);
956 setValue (is_exception, 1, "i32");
957 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
960 var js_name = BINDING.conv_string (property_name);
962 setValue (is_exception, 1, "i32");
963 return BINDING.js_string_to_mono_string ("Invalid property name object '" + js_name + "'");
968 var m = obj [js_name];
969 if (m === Object(m) && obj.__is_mono_proxied__)
970 m.__is_mono_proxied__ = true;
972 return BINDING.js_to_mono_obj (m);
974 var res = e.toString ();
975 setValue (is_exception, 1, "i32");
976 if (res === null || typeof res === "undefined")
977 res = "unknown exception";
978 return BINDING.js_string_to_mono_string (res);
981 mono_wasm_set_object_property: function (js_handle, property_name, value, createIfNotExist, hasOwnProperty, is_exception) {
983 BINDING.bindings_lazy_init ();
985 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
986 if (!requireObject) {
987 setValue (is_exception, 1, "i32");
988 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
991 var property = BINDING.conv_string (property_name);
993 setValue (is_exception, 1, "i32");
994 return BINDING.js_string_to_mono_string ("Invalid property name object '" + property_name + "'");
999 var js_value = BINDING.unbox_mono_obj(value);
1001 if (createIfNotExist) {
1002 requireObject[property] = js_value;
1007 if (!createIfNotExist)
1009 if (!requireObject.hasOwnProperty(property))
1012 if (hasOwnProperty === true) {
1013 if (requireObject.hasOwnProperty(property)) {
1014 requireObject[property] = js_value;
1019 requireObject[property] = js_value;
1024 return BINDING.call_method (BINDING.box_js_bool, null, "im", [ result ]);
1026 mono_wasm_get_by_index: function(js_handle, property_index, is_exception) {
1027 BINDING.bindings_lazy_init ();
1029 var obj = BINDING.mono_wasm_require_handle (js_handle);
1031 setValue (is_exception, 1, "i32");
1032 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1036 var m = obj [property_index];
1037 return BINDING.js_to_mono_obj (m);
1039 var res = e.toString ();
1040 setValue (is_exception, 1, "i32");
1041 if (res === null || typeof res === "undefined")
1042 res = "unknown exception";
1043 return BINDING.js_string_to_mono_string (res);
1046 mono_wasm_set_by_index: function(js_handle, property_index, value, is_exception) {
1047 BINDING.bindings_lazy_init ();
1049 var obj = BINDING.mono_wasm_require_handle (js_handle);
1051 setValue (is_exception, 1, "i32");
1052 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1055 var js_value = BINDING.unbox_mono_obj(value);
1058 obj [property_index] = js_value;
1061 var res = e.toString ();
1062 setValue (is_exception, 1, "i32");
1063 if (res === null || typeof res === "undefined")
1064 res = "unknown exception";
1065 return BINDING.js_string_to_mono_string (res);
1068 mono_wasm_get_global_object: function(global_name, is_exception) {
1069 BINDING.bindings_lazy_init ();
1071 var js_name = BINDING.conv_string (global_name);
1073 var globalObj = undefined;
1076 globalObj = BINDING.mono_wasm_get_global();
1079 globalObj = BINDING.mono_wasm_get_global()[js_name];
1082 if (globalObj === null || typeof globalObj === undefined) {
1083 setValue (is_exception, 1, "i32");
1084 return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found.");
1087 return BINDING.js_to_mono_obj (globalObj);
1089 mono_wasm_release_handle: function(js_handle, is_exception) {
1090 BINDING.bindings_lazy_init ();
1092 BINDING.mono_wasm_free_handle(js_handle);
1094 mono_wasm_release_object: function(js_handle, is_exception) {
1095 BINDING.bindings_lazy_init ();
1097 BINDING.mono_wasm_free_raw_object(js_handle);
1099 mono_wasm_bind_core_object: function(js_handle, gc_handle, is_exception) {
1100 BINDING.bindings_lazy_init ();
1102 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1103 if (!requireObject) {
1104 setValue (is_exception, 1, "i32");
1105 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1108 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1109 requireObject.__mono_gchandle__ = gc_handle;
1112 mono_wasm_bind_host_object: function(js_handle, gc_handle, is_exception) {
1113 BINDING.bindings_lazy_init ();
1115 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1116 if (!requireObject) {
1117 setValue (is_exception, 1, "i32");
1118 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1121 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1122 requireObject.__mono_gchandle__ = gc_handle;
1125 mono_wasm_new: function (core_name, args, is_exception) {
1127 var js_name = BINDING.conv_string (core_name);
1130 setValue (is_exception, 1, "i32");
1131 return BINDING.js_string_to_mono_string ("Core object '" + js_name + "' not found.");
1134 var coreObj = BINDING.mono_wasm_get_global()[js_name];
1136 if (coreObj === null || typeof coreObj === undefined) {
1137 setValue (is_exception, 1, "i32");
1138 return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found.");
1141 var js_args = BINDING.mono_array_to_js_array(args);
1145 // This is all experimental !!!!!!
1146 var allocator = function(constructor, js_args) {
1147 // Not sure if we should be checking for anything here
1148 var argsList = new Array();
1149 argsList[0] = constructor;
1151 argsList = argsList.concat(js_args);
1152 var obj = new (constructor.bind.apply(constructor, argsList ));
1156 var res = allocator(coreObj, js_args);
1157 var gc_handle = BINDING.mono_wasm_free_list.length ? BINDING.mono_wasm_free_list.pop() : BINDING.mono_wasm_ref_counter++;
1158 BINDING.mono_wasm_object_registry[gc_handle] = res;
1159 return BINDING.js_to_mono_obj (gc_handle + 1);
1161 var res = e.toString ();
1162 setValue (is_exception, 1, "i32");
1163 if (res === null || res === undefined)
1164 res = "Error allocating object.";
1165 return BINDING.js_string_to_mono_string (res);
1169 mono_wasm_new_object: function(object_handle_or_function, args, is_exception) {
1170 BINDING.bindings_lazy_init ();
1172 if (!object_handle_or_function) {
1173 return BINDING.js_to_mono_obj ({});
1178 if (typeof object_handle_or_function === 'function')
1179 requireObject = object_handle_or_function;
1181 requireObject = BINDING.mono_wasm_require_handle (object_handle_or_function);
1183 if (!requireObject) {
1184 setValue (is_exception, 1, "i32");
1185 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + object_handle_or_function + "'");
1188 var js_args = BINDING.mono_array_to_js_array(args);
1192 // This is all experimental !!!!!!
1193 var allocator = function(constructor, js_args) {
1194 // Not sure if we should be checking for anything here
1195 var argsList = new Array();
1196 argsList[0] = constructor;
1198 argsList = argsList.concat(js_args);
1199 var obj = new (constructor.bind.apply(constructor, argsList ));
1203 var res = allocator(requireObject, js_args);
1204 return BINDING.extract_mono_obj (res);
1206 var res = e.toString ();
1207 setValue (is_exception, 1, "i32");
1208 if (res === null || res === undefined)
1209 res = "Error allocating object.";
1210 return BINDING.js_string_to_mono_string (res);
1215 mono_wasm_typed_array_to_array: function(js_handle, is_exception) {
1216 BINDING.bindings_lazy_init ();
1218 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1219 if (!requireObject) {
1220 setValue (is_exception, 1, "i32");
1221 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1224 return BINDING.js_typed_array_to_array(requireObject);
1226 mono_wasm_typed_array_copy_to: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) {
1227 BINDING.bindings_lazy_init ();
1229 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1230 if (!requireObject) {
1231 setValue (is_exception, 1, "i32");
1232 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1235 var res = BINDING.typedarray_copy_to(requireObject, pinned_array, begin, end, bytes_per_element);
1236 return BINDING.js_to_mono_obj (res)
1238 mono_wasm_typed_array_from: function(pinned_array, begin, end, bytes_per_element, type, is_exception) {
1239 BINDING.bindings_lazy_init ();
1240 var res = BINDING.typed_array_from(pinned_array, begin, end, bytes_per_element, type);
1241 return BINDING.js_to_mono_obj (res)
1243 mono_wasm_typed_array_copy_from: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) {
1244 BINDING.bindings_lazy_init ();
1246 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1247 if (!requireObject) {
1248 setValue (is_exception, 1, "i32");
1249 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1252 var res = BINDING.typedarray_copy_from(requireObject, pinned_array, begin, end, bytes_per_element);
1253 return BINDING.js_to_mono_obj (res)
1259 autoAddDeps(BindingSupportLib, '$BINDING')
1260 mergeInto(LibraryManager.library, BindingSupportLib)