[wasm] Unbreak the debugger and harden it against bad assemblies. (#11011)
[mono-project.git] / sdks / wasm / library_mono.js
blobee910bdc56fbc00fd55936e3ed088fe522aca866
2 var MonoSupportLib = {
3         $MONO__postset: 'Module["pump_message"] = MONO.pump_message',
4         $MONO: {
5                 pump_count: 0,
6                 timeout_queue: [],
7                 mono_wasm_runtime_is_ready : false,
8                 pump_message: function () {
9                         if (!this.mono_background_exec)
10                                 this.mono_background_exec = Module.cwrap ("mono_background_exec", 'void', [ ]);
11                         while (MONO.timeout_queue.length > 0) {
12                                 --MONO.pump_count;
13                                 MONO.timeout_queue.shift()();
14                         }
15                         while (MONO.pump_count > 0) {
16                                 --MONO.pump_count;
17                                 this.mono_background_exec ();
18                         }
19                 },
21                 mono_wasm_get_call_stack: function() {
22                         if (!this.mono_wasm_current_bp_id)
23                                 this.mono_wasm_current_bp_id = Module.cwrap ("mono_wasm_current_bp_id", 'number', [ ]);
24                         if (!this.mono_wasm_enum_frames)
25                                 this.mono_wasm_enum_frames = Module.cwrap ("mono_wasm_enum_frames", 'void', [ ]);
27                         var bp_id = this.mono_wasm_current_bp_id ();
28                         this.active_frames = [];
29                         this.mono_wasm_enum_frames ();
31                         var the_frames = this.active_frames;
32                         this.active_frames = [];
33                         return {
34                                 "breakpoint_id": bp_id,
35                                 "frames": the_frames,
36                         };
37                 },
39                 mono_wasm_get_variables: function(scope, var_list) {
40                         if (!this.mono_wasm_get_var_info)
41                                 this.mono_wasm_get_var_info = Module.cwrap ("mono_wasm_get_var_info", 'void', [ 'number', 'number']);
43                         //FIXME it would be more efficient to do a single call passing an array with var_list as argument instead
44                         this.var_info = [];
45                         for (var i = 0; i <  var_list.length; ++i)
46                                 this.mono_wasm_get_var_info (scope, var_list [i]);
48                         var res = this.var_info;
49                         this.var_info = []
51                         return res;
52                 },
54                 mono_wasm_start_single_stepping: function (kind) {
55                         console.log (">> mono_wasm_start_single_stepping " + kind);
56                         if (!this.mono_wasm_setup_single_step)
57                                 this.mono_wasm_setup_single_step = Module.cwrap ("mono_wasm_setup_single_step", 'void', [ 'number']);
59                         this.mono_wasm_setup_single_step (kind);
60                 },
62                 mono_wasm_runtime_ready: function () {
63                         console.log (">>mono_wasm_runtime_ready");
64                         this.mono_wasm_runtime_is_ready = true;
65                         debugger;
66                 },
68                 mono_wasm_set_breakpoint: function (assembly, method_token, il_offset) {
69                         if (!this.mono_wasm_set_bp)
70                                 this.mono_wasm_set_bp = Module.cwrap ('mono_wasm_set_breakpoint', 'number', ['string', 'number', 'number']);
72                         return this.mono_wasm_set_bp (assembly, method_token, il_offset)
73                 },
75                 mono_wasm_remove_breakpoint: function (breakpoint_id) {
76                         if (!this.mono_wasm_del_bp)
77                                 this.mono_wasm_del_bp = Module.cwrap ('mono_wasm_remove_breakpoint', 'number', ['number']);
79                         return this.mono_wasm_del_bp (breakpoint_id);
80                 },
82                 mono_load_runtime_and_bcl: function (vfs_prefix, deploy_prefix, enable_debugging, file_list, loaded_cb, fetch_file_cb) {
83                         Module.FS_createPath ("/", vfs_prefix, true, true);
85                         var pending = file_list.length;
86                         var loaded_files = [];
87                         var mono_wasm_add_assembly = Module.cwrap ('mono_wasm_add_assembly', null, ['string', 'number', 'number']);
89                         if (!fetch_file_cb) {
90                                 if (ENVIRONMENT_IS_NODE) {
91                                         var fs = require('fs');
92                                         fetch_file_cb = function (asset) {
93                                                 console.log("Loading... " + asset);
94                                                 var binary = fs.readFileSync (asset);
95                                                 var resolve_func2 = function(resolve, reject) {
96                                                         resolve(new Uint8Array (binary));
97                                                 };
99                                                 var resolve_func1 = function(resolve, reject) {
100                                                         var response = {
101                                                                 ok: true,
102                                                                 url: asset,
103                                                                 arrayBuffer: function() {
104                                                                         return new Promise(resolve_func2);
105                                                                 }
106                                                         };
107                                                         resolve(response);
108                                                 };
110                                                 return new Promise(resolve_func1);
111                                         };
112                                 } else {
113                                         fetch_file_cb = function (asset) {
114                                                 return fetch (asset, { credentials: 'same-origin' });
115                                         }
116                                 }
117                         }
119                         file_list.forEach (function(file_name) {
120                                 var fetch_promise = fetch_file_cb (deploy_prefix + "/" + file_name);
122                                 fetch_promise.then (function (response) {
123                                         if (!response.ok)
124                                                 throw "failed to load '" + file_name + "'";
125                                         loaded_files.push (response.url);
126                                         return response ['arrayBuffer'] ();
127                                 }).then (function (blob) {
128                                         var asm = new Uint8Array (blob);
129                                         var memory = Module._malloc(asm.length);
130                                         var heapBytes = new Uint8Array(Module.HEAPU8.buffer, memory, asm.length);
131                                         heapBytes.set (asm);
132                                         mono_wasm_add_assembly (file_name, memory, asm.length);
134                                         console.log ("Loaded: " + file_name);
135                                         --pending;
136                                         if (pending == 0) {
137                                                 MONO.loaded_files = loaded_files;
138                                                 var load_runtime = Module.cwrap ('mono_wasm_load_runtime', null, ['string', 'number']);
140                                                 console.log ("initializing mono runtime");
141                                                 load_runtime (vfs_prefix, enable_debugging);
142                                                 MONO.mono_wasm_runtime_ready ();
143                                                 loaded_cb ();
144                                         }
145                                 });
146                         });
147                 },
149                 mono_wasm_get_loaded_files: function() {
150                         console.log(">>>mono_wasm_get_loaded_files");
151                         return this.loaded_files;
152                 },
153                 
154                 mono_wasm_clear_all_breakpoints: function() {
155                         if (this.mono_clear_bps)
156                                 this.mono_clear_bps = Module.cwrap ('mono_wasm_clear_all_breakpoints', 'void', [ ]);
157                         this.mono_clear_bps ();
158                 },
159                 
160         },
162         mono_wasm_add_bool_var: function(var_value) {
163                 MONO.var_info.push({
164                         value: {
165                                 type: "boolean",
166                                 value: var_value != 0,
167                         }
168                 });
169         },
171         mono_wasm_add_int_var: function(var_value) {
172                 MONO.var_info.push({
173                         value: {
174                                 type: "number",
175                                 value: var_value,
176                         }
177                 });
178         },
180         mono_wasm_add_long_var: function(var_value) {
181                 MONO.var_info.push({
182                         value: {
183                                 type: "number",
184                                 value: var_value,
185                         }
186                 });
187         },
189         mono_wasm_add_float_var: function(var_value) {
190                 MONO.var_info.push({
191                         value: {
192                                 type: "number",
193                                 value: var_value,
194                         }
195                 });
196         },
198         mono_wasm_add_double_var: function(var_value) {
199                 MONO.var_info.push({
200                         value: {
201                                 type: "number",
202                                 value: var_value,
203                         }
204                 });
205         },
207         mono_wasm_add_string_var: function(var_value) {
208                 if (var_value == 0) {
209                         MONO.var_info.push({
210                                 value: {
211                                         type: "object",
212                                         subtype: "null"
213                                 }
214                         });
215                 } else {
216                         MONO.var_info.push({
217                                 value: {
218                                         type: "string",
219                                         value: Module.UTF8ToString (var_value),
220                                 }
221                         });
222                 }
223         },
226         mono_wasm_add_frame: function(il, method, name) {
227                 MONO.active_frames.push( {
228                         il_pos: il,
229                         method_token: method,
230                         assembly_name: Module.UTF8ToString (name)
231                 });
232         },
234         schedule_background_exec: function () {
235                 ++MONO.pump_count;
236                 if (ENVIRONMENT_IS_WEB) {
237                         window.setTimeout (MONO.pump_message, 0);
238                 }
239         },
241         mono_set_timeout: function (timeout, id) {
242                 if (!this.mono_set_timeout_exec)
243                         this.mono_set_timeout_exec = Module.cwrap ("mono_set_timeout_exec", 'void', [ 'number' ]);
244                 if (ENVIRONMENT_IS_WEB) {
245                         window.setTimeout (function () {
246                                 this.mono_set_timeout_exec (id);
247                         }, timeout);
248                 } else {
249                         ++MONO.pump_count;
250                         MONO.timeout_queue.push(function() {
251                                 this.mono_set_timeout_exec (id);
252                         })
253                 }
254         },
256         mono_wasm_fire_bp: function () {
257                 console.log ("mono_wasm_fire_bp");
258                 debugger;
259         }
262 autoAddDeps(MonoSupportLib, '$MONO')
263 mergeInto(LibraryManager.library, MonoSupportLib)