183 lines
6.4 KiB
JavaScript
183 lines
6.4 KiB
JavaScript
(function () {
|
|
// Implement just enough of the DotNet.* API surface for unmarshalled interop calls to work
|
|
// in the cases used in this project
|
|
window.DotNet = {
|
|
jsCallDispatcher: {
|
|
findJSFunction: function (identifier) {
|
|
return window[identifier];
|
|
}
|
|
}
|
|
};
|
|
|
|
window.initMono = function initMono(loadAssemblyUrls, onReadyCallback) {
|
|
window.Browser = {
|
|
init: function () { },
|
|
asyncLoad: asyncLoad
|
|
};
|
|
|
|
window.Module = {
|
|
print: function (line) { console.log(line); },
|
|
printEr: function (line) { console.error(line); },
|
|
locateFile: function (fileName) {
|
|
switch (fileName) {
|
|
case 'mono.wasm': return '/_framework/wasm/mono.wasm';
|
|
case 'mono.asm.js': return '/_framework/asmjs/mono.asm.js';
|
|
default: return fileName;
|
|
}
|
|
},
|
|
preloadPlugins: [],
|
|
preRun: [function () {
|
|
preloadAssemblies(loadAssemblyUrls);
|
|
}],
|
|
postRun: [function () {
|
|
var load_runtime = Module.cwrap('mono_wasm_load_runtime', null, ['string', 'number']);
|
|
load_runtime('appBinDir', 1);
|
|
MONO.mono_wasm_runtime_is_ready = true;
|
|
onReadyCallback();
|
|
}]
|
|
};
|
|
|
|
addScriptTagsToDocument();
|
|
};
|
|
|
|
window.invokeMonoMethod = function invokeMonoMethod(assemblyName, namespace, typeName, methodName, args) {
|
|
var assembly_load = Module.cwrap('mono_wasm_assembly_load', 'number', ['string']);
|
|
var find_class = Module.cwrap('mono_wasm_assembly_find_class', 'number', ['number', 'string', 'string']);
|
|
var find_method = Module.cwrap('mono_wasm_assembly_find_method', 'number', ['number', 'string', 'number']);
|
|
|
|
var assembly = assembly_load(assemblyName);
|
|
var type = find_class(assembly, namespace, typeName);
|
|
var method = find_method(type, methodName, -1);
|
|
|
|
var stack = Module.stackSave();
|
|
try {
|
|
var resultPtr = callMethod(method, null, args);
|
|
return dotnetStringToJavaScriptString(resultPtr);
|
|
}
|
|
finally {
|
|
Module.stackRestore(stack);
|
|
}
|
|
};
|
|
|
|
window.dotnetStringToJavaScriptString = function dotnetStringToJavaScriptString(mono_obj) {
|
|
if (mono_obj === 0)
|
|
return null;
|
|
var mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']);
|
|
var raw = mono_string_get_utf8(mono_obj);
|
|
var res = Module.UTF8ToString(raw);
|
|
Module._free(raw);
|
|
return res;
|
|
};
|
|
|
|
window.javaScriptStringToDotNetString = function dotnetStringToJavaScriptString(javaScriptString) {
|
|
var mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']);
|
|
return mono_string(javaScriptString);
|
|
};
|
|
|
|
function preloadAssemblies(loadAssemblyUrls) {
|
|
var loadBclAssemblies = [
|
|
'netstandard',
|
|
'mscorlib',
|
|
'System',
|
|
'System.Core',
|
|
'System.Net.Http',
|
|
];
|
|
|
|
var allAssemblyUrls = loadAssemblyUrls
|
|
.concat(loadBclAssemblies.map(function (name) { return '_framework/_bin/' + name + '.dll'; }));
|
|
|
|
Module.FS_createPath('/', 'appBinDir', true, true);
|
|
|
|
MONO.loaded_files = []; // Used by debugger
|
|
allAssemblyUrls.forEach(function (url) {
|
|
FS.createPreloadedFile('appBinDir', getFileNameFromUrl(url), url, true, false,
|
|
/* success */ function() { MONO.loaded_files.push(toAbsoluteUrl(url)); },
|
|
/* failure */ function onError(err) { throw err; }
|
|
);
|
|
});
|
|
}
|
|
|
|
var anchorTagForAbsoluteUrlConversions = document.createElement('a');
|
|
function toAbsoluteUrl(possiblyRelativeUrl) {
|
|
anchorTagForAbsoluteUrlConversions.href = possiblyRelativeUrl;
|
|
return anchorTagForAbsoluteUrlConversions.href;
|
|
}
|
|
|
|
function asyncLoad(url, onload, onerror) {
|
|
var xhr = new XMLHttpRequest;
|
|
xhr.open('GET', url, /* async: */ true);
|
|
xhr.responseType = 'arraybuffer';
|
|
xhr.onload = function xhr_onload() {
|
|
if (xhr.status === 200 || xhr.status === 0 && xhr.response) {
|
|
var asm = new Uint8Array(xhr.response);
|
|
onload(asm);
|
|
} else {
|
|
onerror(xhr);
|
|
}
|
|
};
|
|
xhr.onerror = onerror;
|
|
xhr.send(null);
|
|
}
|
|
|
|
function callMethod(method, target, args) {
|
|
var stack = Module.stackSave();
|
|
var invoke_method = Module.cwrap('mono_wasm_invoke_method', 'number', ['number', 'number', 'number']);
|
|
|
|
try {
|
|
var argsBuffer = Module.stackAlloc(args.length);
|
|
var exceptionFlagManagedInt = Module.stackAlloc(4);
|
|
for (var i = 0; i < args.length; ++i) {
|
|
var argVal = args[i];
|
|
if (typeof argVal === 'number') {
|
|
var managedInt = Module.stackAlloc(4);
|
|
Module.setValue(managedInt, argVal, 'i32');
|
|
Module.setValue(argsBuffer + i * 4, managedInt, 'i32');
|
|
} else if (typeof argVal === 'string') {
|
|
var managedString = javaScriptStringToDotNetString(argVal);
|
|
Module.setValue(argsBuffer + i * 4, managedString, 'i32');
|
|
} else {
|
|
throw new Error('Unsupported arg type: ' + typeof argVal);
|
|
}
|
|
}
|
|
Module.setValue(exceptionFlagManagedInt, 0, 'i32');
|
|
|
|
var res = invoke_method(method, target, argsBuffer, exceptionFlagManagedInt);
|
|
|
|
if (Module.getValue(exceptionFlagManagedInt, 'i32') !== 0) {
|
|
throw new Error(dotnetStringToJavaScriptString(res));
|
|
}
|
|
|
|
return res;
|
|
} finally {
|
|
Module.stackRestore(stack);
|
|
}
|
|
}
|
|
|
|
function addScriptTagsToDocument() {
|
|
// Load either the wasm or asm.js version of the Mono runtime
|
|
var browserSupportsNativeWebAssembly = typeof WebAssembly !== 'undefined' && WebAssembly.validate;
|
|
var monoRuntimeUrlBase = '/_framework/' + (browserSupportsNativeWebAssembly ? 'wasm' : 'asmjs');
|
|
var monoRuntimeScriptUrl = monoRuntimeUrlBase + '/mono.js';
|
|
|
|
if (!browserSupportsNativeWebAssembly) {
|
|
// In the asmjs case, the initial memory structure is in a separate file we need to download
|
|
var meminitXHR = Module['memoryInitializerRequest'] = new XMLHttpRequest();
|
|
meminitXHR.open('GET', monoRuntimeUrlBase + '/mono.js.mem');
|
|
meminitXHR.responseType = 'arraybuffer';
|
|
meminitXHR.send(null);
|
|
}
|
|
|
|
var scriptElem = document.createElement('script');
|
|
scriptElem.src = monoRuntimeScriptUrl;
|
|
document.body.appendChild(scriptElem);
|
|
}
|
|
|
|
function getFileNameFromUrl(url) {
|
|
var lastSegment = url.substring(url.lastIndexOf('/') + 1);
|
|
var queryStringStartPos = lastSegment.indexOf('?');
|
|
var filename = queryStringStartPos < 0 ? lastSegment : lastSegment.substring(0, queryStringStartPos);
|
|
return filename;
|
|
}
|
|
|
|
})();
|