diff --git a/index.html b/index.html index b126e5120b..4df3486e83 100644 --- a/index.html +++ b/index.html @@ -39,7 +39,6 @@ - @@ -391,13 +390,7 @@ } }); $('#versionSelector').change(function() { - Module = null; - compileJSON = null; - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = 'bin/' + $('#versionSelector').val(); - $('head').append(script); - onCompilerLoaded(); + loadVersion($('#versionSelector').val()); }); // ----------------- resizeable ui --------------- @@ -497,14 +490,11 @@ var inputIncludingImports = includeLocalAndRemoteImports(input, compile); if (!inputIncludingImports) return; var optimize = document.querySelector('#optimize').checked; - - try { - var data = $.parseJSON(compileJSON(inputIncludingImports, optimize ? 1 : 0)); - } catch (exception) { - renderError("Uncaught JavaScript Exception:\n" + exception); - return; - } + compileJSON(inputIncludingImports, optimize ? 1 : 0); + }; + var compilationFinished = function(result) { + var data = $.parseJSON(result); var noFatalErrors = true; // ie warnings are ok if (data['error'] !== undefined) { @@ -517,10 +507,9 @@ if (errortype(err) !== 'warning') noFatalErrors = false; }); } - - if (noFatalErrors) renderContracts(data, input); - - } + + if (noFatalErrors) renderContracts(data, editor.getValue()); + }; var compileTimeout = null; var onChange = function() { @@ -537,8 +526,18 @@ }; var onCompilerLoaded = function() { - compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]); - $('#version').text(Module.cwrap("version", "string", [])()); + if (worker === null) { + var compile = Module.cwrap("compileJSON", "string", ["string", "number"]); + compileJSON = function(source, optimize, cb) { + try { + var result = compile(source, optimize); + } catch (exception) { + result = JSON.stringify({error: 'Uncaught JavaScript exception:\n' + exception}); + } + compilationFinished(result); + }; + $('#version').text(Module.cwrap("version", "string", [])()); + } previousInput = ''; onChange(); }; @@ -567,8 +566,53 @@ return input; } - if (Module) - onCompilerLoaded(); + var initializeWorker = function() { + if (worker !== null) + worker.terminate(); + worker = new Worker('worker.js'); + worker.addEventListener('message', function(msg) { + var data = msg.data; + switch (data.cmd) { + case 'versionLoaded': + $('#version').text(data.data); + onCompilerLoaded(); + break; + case 'compiled': + compilationFinished(data.data); + break; + }; + }); + worker.onerror = function(msg) { console.log(msg.data); }; + worker.addEventListener('error', function(msg) { console.log(msg.data); }); + compileJSON = function(source, optimize) { + worker.postMessage({cmd: 'compile', source: source, optimize: optimize}); + }; + }; + var worker = null; + var loadVersion = function(version) { + $('#version').text("(loading)"); + var isFirefox = typeof InstallTrigger !== 'undefined'; + if (document.location.protocol != 'file:' && Worker !== undefined && isFirefox) { + // Workers cannot load js on "file:"-URLs and we get a + // "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium, + // resort to non-worker version in that case. + initializeWorker(); + worker.postMessage({cmd: 'loadVersion', data: 'bin/' + version}); + } else { + Module = null; + compileJSON = function(source, optimize) { compilationFinished('{}'); }; + var newScript = document.createElement('script'); + newScript.type = 'text/javascript'; + newScript.src = 'bin/' + version; + document.getElementsByTagName("head")[0].appendChild(newScript); + var check = window.setInterval(function() { + if (!Module) return; + window.clearInterval(check); + onCompilerLoaded(); + }, 200); + } + }; + loadVersion('soljson-latest.js'); editor.getSession().on('change', onChange); diff --git a/worker.js b/worker.js new file mode 100644 index 0000000000..60cd302b2c --- /dev/null +++ b/worker.js @@ -0,0 +1,23 @@ +var version = function() { return '(loading)'; } +var compileJSON = function() { return ''; } +addEventListener('message', function(e) { + var data = e.data; + switch (data.cmd) { + case 'loadVersion': + delete Module; + version = null; + compileJSON = null; + + importScripts(data.data); + version = Module.cwrap("version", "string", []); + compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]); + postMessage({cmd: 'versionLoaded', data: version()}); + break; + case 'version': + postMessage({cmd: 'versionLoaded', data: version()}); + break; + case 'compile': + postMessage({cmd: 'compiled', data: compileJSON(data.source, data.optimize)}); + break; + } +}, false);