Use the compiler callback method for resolving imports if available.

pull/1/head
chriseth 9 years ago
parent e04e22cbc8
commit 3e83423915
  1. 107
      index.html
  2. 35
      index.js
  3. 16
      worker.js

@ -512,7 +512,7 @@
var previousInput = ''; var previousInput = '';
var sourceAnnotations = []; var sourceAnnotations = [];
var compile = function() { var compile = function(missingInputs) {
editor.getSession().clearAnnotations(); editor.getSession().clearAnnotations();
sourceAnnotations = []; sourceAnnotations = [];
editor.getSession().removeMarker(errMarkerId); editor.getSession().removeMarker(errMarkerId);
@ -522,13 +522,17 @@
var files = {}; var files = {};
files[fileNameFromKey(SOL_CACHE_FILE)] = input; files[fileNameFromKey(SOL_CACHE_FILE)] = input;
var input = gatherImports(files, compile); gatherImports(files, missingInputs, function(input, error) {
if (!input) return; $('#output').empty();
var optimize = document.querySelector('#optimize').checked; if (input === null) {
renderError(error);
compileJSON(input, optimize ? 1 : 0); } else {
var optimize = document.querySelector('#optimize').checked;
compileJSON(input, optimize ? 1 : 0);
}
});
}; };
var compilationFinished = function(result) { var compilationFinished = function(result, missingInputs) {
var data = $.parseJSON(result); var data = $.parseJSON(result);
var noFatalErrors = true; // ie warnings are ok var noFatalErrors = true; // ie warnings are ok
@ -543,7 +547,10 @@
}); });
} }
if (noFatalErrors && !hidingRHP) renderContracts(data, editor.getValue()); if (missingInputs !== undefined && missingInputs.length > 0)
compile(missingInputs);
else if (noFatalErrors && !hidingRHP)
renderContracts(data, editor.getValue());
}; };
var compileTimeout = null; var compileTimeout = null;
@ -563,7 +570,18 @@
var onCompilerLoaded = function() { var onCompilerLoaded = function() {
if (worker === null) { if (worker === null) {
var compile; var compile;
if ('_compileJSONMulti' in Module) { var missingInputs = [];
if ('_compileJSONCallback' in Module) {
compilerAcceptsMultipleFiles = true;
var missingInputsCallback = Module.Runtime.addFunction(function(path, contents, error) {
missingInputs.push(Module.Pointer_stringify(path));
});
var compileInternal = Module.cwrap("compileJSONCallback", "string", ["string", "number", "number"]);
compile = function(input, optimize) {
missingInputs.length = 0;
return compileInternal(input, optimize, missingInputsCallback);
};
} else if ('_compileJSONMulti' in Module) {
compilerAcceptsMultipleFiles = true; compilerAcceptsMultipleFiles = true;
compile = Module.cwrap("compileJSONMulti", "string", ["string", "number"]); compile = Module.cwrap("compileJSONMulti", "string", ["string", "number"]);
} else { } else {
@ -576,7 +594,7 @@
} catch (exception) { } catch (exception) {
result = JSON.stringify({error: 'Uncaught JavaScript exception:\n' + exception}); result = JSON.stringify({error: 'Uncaught JavaScript exception:\n' + exception});
} }
compilationFinished(result); compilationFinished(result, missingInputs);
}; };
$('#version').text(Module.cwrap("version", "string", [])()); $('#version').text(Module.cwrap("version", "string", [])());
} }
@ -585,49 +603,54 @@
}; };
var cachedRemoteFiles = {}; var cachedRemoteFiles = {};
function gatherImports(files, asyncCallback, needAsync) { function gatherImports(files, importHints, cb) {
importHints = importHints || [];
if (!compilerAcceptsMultipleFiles) if (!compilerAcceptsMultipleFiles)
return files[fileNameFromKey(SOL_CACHE_FILE)]; {
cb(files[fileNameFromKey(SOL_CACHE_FILE)]);
return;
}
var importRegex = /import\s[\'\"]([^\'\"]+)[\'\"];/g; var importRegex = /import\s[\'\"]([^\'\"]+)[\'\"];/g;
var reloop = false; var reloop = false;
do { do {
reloop = false; reloop = false;
for (var fileName in files) { for (var fileName in files) {
var match; var match;
while (match = importRegex.exec(files[fileName])) { while (match = importRegex.exec(files[fileName]))
var m = match[1]; importHints.push(match[1]);
if (m in files) continue; }
if (getFiles().indexOf(fileKey(m)) !== -1) { while (importHints.length > 0) {
files[m] = window.localStorage[fileKey(match[1])]; var m = importHints.pop();
reloop = true; if (m in files) continue;
} else if (m in cachedRemoteFiles) { if (getFiles().indexOf(fileKey(m)) !== -1) {
files[m] = cachedRemoteFiles[m]; files[m] = window.localStorage[fileKey(m)];
reloop = true; reloop = true;
} else if (githubMatch = /^(https?:\/\/)?(www.)?github.com\/([^\/]*\/[^\/]*)\/(.*)/.exec(m)) { } else if (m in cachedRemoteFiles) {
$.getJSON('https://api.github.com/repos/' + githubMatch[3] + '/contents/' + githubMatch[4], function(result) { files[m] = cachedRemoteFiles[m];
var content; reloop = true;
if ('content' in result) } else if (githubMatch = /^(https?:\/\/)?(www.)?github.com\/([^\/]*\/[^\/]*)\/(.*)/.exec(m)) {
content = Base64.decode(result.content); $('#output').append($('<div/>').append($('<pre/>').text("Loading github.com/" + githubMatch[3] + " ...")));
else $.getJSON('https://api.github.com/repos/' + githubMatch[3] + '/contents/' + githubMatch[4], function(result) {
content = "\"" + m + "\" NOT FOUND"; //@TODO handle this better if ('content' in result)
cachedRemoteFiles[m] = content; {
files[m] = content; var content = Base64.decode(result.content);
gatherImports(files, asyncCallback, true);
}).fail(function(){
var content = "\"" + m + "\" NOT FOUND"; //@TODO handle this better
cachedRemoteFiles[m] = content; cachedRemoteFiles[m] = content;
files[m] = content; files[m] = content;
gatherImports(files, asyncCallback, true); gatherImports(files, importHints, cb);
}); }
return null; else
} cb(null, "Unable to import \"" + m + "\"");
}).fail(function(){
cb(null, "Unable to import \"" + m + "\"");
});
return;
} else {
cb(null, "Unable to import \"" + m + "\"");
return;
} }
} }
} while (reloop); } while (reloop);
var input = JSON.stringify({'sources':files}); cb(JSON.stringify({'sources':files}));
if (needAsync)
asyncCallback(input);
return input;
} }
var initializeWorker = function() { var initializeWorker = function() {
@ -643,7 +666,7 @@
onCompilerLoaded(); onCompilerLoaded();
break; break;
case 'compiled': case 'compiled':
compilationFinished(data.data); compilationFinished(data.data, data.missingInputs);
break; break;
}; };
}); });

@ -5,9 +5,42 @@ function setupMethods (soljson){
'_compileJSONMulti' in soljson ? '_compileJSONMulti' in soljson ?
soljson.cwrap("compileJSONMulti", "string", ["string", "number"]) : soljson.cwrap("compileJSONMulti", "string", ["string", "number"]) :
null; null;
var compileJSONCallback = null;
if ('_compileJSONCallback' in soljson)
{
/// TODO: Allocating memory and copying the strings over
/// to the emscripten runtime does not seem to work.
var copyString = function(str, ptr) {
var buffer = soljson._malloc(str.length + 1);
soljson.writeStringToMemory(str, buffer);
soljson.setValue(ptr, buffer, '*');
};
var wrapCallback = function(callback) {
return soljson.Runtime.addFunction(function(path, contents, error) {
// path is char*, contents is char**, error is char**
// TODO copying the results does not seem to work.
// This is not too bad, because most of the requests
// cannot be answered synchronously anyway.
var result = callback(soljson.Pointer_stringify(path));
if (typeof(result.contents) === typeof(''))
copyString(result.contents, contents);
if (typeof(result.error) === typeof(''))
copyString(result.error, error);
});
};
var compileInternal = soljson.cwrap("compileJSONCallback", "string", ["string", "number", "number"]);
compileJSONCallback = function(input, optimize, readCallback) {
var cb = wrapCallback(readCallback);
var output = compileInternal(input, optimize, cb);
soljson.Runtime.removeFunction(cb);
return output;
};
}
var compile = function(input, optimise) { var compile = function(input, optimise, readCallback) {
var result = ''; var result = '';
if (readCallback !== undefined && compileJSONCallback !== null)
result = compileJSONCallback(JSON.stringify(input), optimise, readCallback);
if (typeof(input) != typeof('') && compileJSONMulti !== null) if (typeof(input) != typeof('') && compileJSONMulti !== null)
result = compileJSONMulti(JSON.stringify(input), optimise); result = compileJSONMulti(JSON.stringify(input), optimise);
else else

@ -2,6 +2,7 @@ var version = function() { return '(loading)'; }
var compileJSON = function() { return ''; } var compileJSON = function() { return ''; }
addEventListener('message', function(e) { addEventListener('message', function(e) {
var data = e.data; var data = e.data;
var missingInputs = [];
switch (data.cmd) { switch (data.cmd) {
case 'loadVersion': case 'loadVersion':
delete Module; delete Module;
@ -10,7 +11,17 @@ addEventListener('message', function(e) {
importScripts(data.data); importScripts(data.data);
version = Module.cwrap("version", "string", []); version = Module.cwrap("version", "string", []);
if ('_compileJSONMulti' in Module) if ('_compileJSONCallback' in Module)
{
compileJSONInternal = Module.cwrap("compileJSONCallback", "string", ["string", "number", "number"]);
var missingInputCallback = Module.Runtime.addFunction(function(path) {
missingInputs.push(Module.Pointer_stringify(path));
});
compileJSON = function(input, optimize) {
return compileJSONInternal(input, optimize, missingInputCallback);
};
}
else if ('_compileJSONMulti' in Module)
compileJSON = Module.cwrap("compileJSONMulti", "string", ["string", "number"]); compileJSON = Module.cwrap("compileJSONMulti", "string", ["string", "number"]);
else else
compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]); compileJSON = Module.cwrap("compileJSON", "string", ["string", "number"]);
@ -21,7 +32,8 @@ addEventListener('message', function(e) {
}); });
break; break;
case 'compile': case 'compile':
postMessage({cmd: 'compiled', data: compileJSON(data.source, data.optimize)}); missingInputs
postMessage({cmd: 'compiled', data: compileJSON(data.source, data.optimize)}, missingInputs: missingInputs);
break; break;
} }
}, false); }, false);

Loading…
Cancel
Save