Merge pull request #525 from embark-framework/bug_fix/solc-loading-issue

Fix for solc loading issue
This commit is contained in:
Iuri Matias 2018-06-15 17:28:53 -04:00 committed by GitHub
commit 5614998f89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 3574 additions and 3465 deletions

View File

@ -16,6 +16,7 @@ class Engine {
this.logLevel = options.logLevel;
this.events = options.events;
this.context = options.context;
this.useDashboard = options.useDashboard;
}
init(_options) {
@ -185,7 +186,7 @@ class Engine {
this.ipc.serve();
}
this.registerModule('solidity', {ipc: this.ipc});
this.registerModule('solidity', {ipc: this.ipc, useDashboard: this.useDashboard});
this.registerModule('vyper');
this.registerModule('profiler');
this.registerModule('fuzzer');

View File

@ -80,7 +80,8 @@ class Embark {
embarkConfig: options.embarkConfig || 'embark.json',
logFile: options.logFile,
logLevel: options.logLevel,
context: self.context
context: self.context,
useDashboard: options.useDashboard
});
engine.init();

View File

@ -61,10 +61,10 @@ class IPFS {
return cb({name: "IPFS ", status: 'off'});
}
if (body.Version) {
self.logger.trace("Swarm available");
self.logger.trace("IPFS available");
return cb({name: ("IPFS " + body.Version), status: 'on'});
}
self.logger.trace("Swarm available");
self.logger.trace("IPFS available");
return cb({name: "IPFS ", status: 'on'});
}
});

View File

@ -10,6 +10,7 @@ class Solidity {
this.contractDirectories = embark.config.contractDirectories;
this.solcAlreadyLoaded = false;
this.solcW = null;
this.useDashboard = options.useDashboard;
embark.registerCompiler(".sol", this.compile_solidity.bind(this));
}
@ -49,7 +50,7 @@ class Solidity {
if (self.solcAlreadyLoaded) {
return callback();
}
self.solcW = new SolcW({logger: self.logger, events: self.events, ipc: self.ipc});
self.solcW = new SolcW({logger: self.logger, events: self.events, ipc: self.ipc, useDashboard: self.useDashboard});
self.logger.info(__("loading solc compiler") + "..");
self.solcW.load_compiler(function (err) {
@ -75,7 +76,10 @@ class Solidity {
}
};
self.solcW.compile(jsonObj, function (output) {
self.solcW.compile(jsonObj, function (err, output) {
if(err){
return callback(err);
}
if (output.errors) {
for (let i=0; i<output.errors.length; i++) {
if (output.errors[i].type === 'Warning') {

View File

@ -2,11 +2,19 @@ const fs = require('fs-extra');
const path = require('path');
const constants = require('../../constants');
const Utils = require('../../utils/utils');
const ProcessWrapper = require('../../process/processWrapper');
const PluginManager = require('live-plugin-manager-git-fix').PluginManager;
const NpmTimer = require('../../versions/npmTimer');
class SolcProcess extends ProcessWrapper {
constructor(options){
super();
this._logger = options.logger;
this._showSpinner = options.showSpinner === true;
}
findImports(filename) {
if (filename.startsWith('http') || filename.startsWith('git')) {
const fileObj = Utils.getExternalContractUrl(filename);
@ -24,34 +32,59 @@ class SolcProcess extends ProcessWrapper {
return {error: 'File not found'};
}
loadCompiler(solcLocation) {
this.solc = require(solcLocation);
installAndLoadCompiler(solcVersion, packagePath){
let self = this;
return new Promise((resolve, reject) => {
let manager = new PluginManager({pluginsPath: packagePath});
let timer;
if (!fs.existsSync(packagePath)) {
timer = new NpmTimer({logger: self._logger, packageName: 'solc', version: solcVersion, showSpinner: self._showSpinner});
}
if(timer) timer.start();
manager.install('solc', solcVersion).then(() => {
self.solc = manager.require('solc');
if(timer) timer.end();
resolve();
}).catch(reject);
});
}
compile(jsonObj, cb) {
// TODO: only available in 0.4.11; need to make versions warn about this
let output = this.solc.compileStandardWrapper(JSON.stringify(jsonObj), this.findImports);
cb(output);
try {
let output = this.solc.compileStandardWrapper(JSON.stringify(jsonObj), this.findImports);
cb(null, output);
} catch (err) {
cb(err.message);
}
}
}
let solcProcess;
process.on('message', function (msg) {
process.on('message', (msg) => {
if (msg.action === "init") {
solcProcess = new SolcProcess(msg.options);
return process.send({result: "initiated"});
}
if (msg.action === 'loadCompiler') {
solcProcess.loadCompiler(msg.requirePath);
process.send({result: "loadedCompiler"});
else if (msg.action === 'loadCompiler') {
solcProcess.solc = require('solc');
return process.send({result: "loadedCompiler"});
}
if (msg.action === 'compile') {
solcProcess.compile(msg.jsonObj, (output) => {
process.send({result: "compilation-" + msg.id, output: output});
else if (msg.action == 'installAndLoadCompiler') {
solcProcess.installAndLoadCompiler(msg.solcVersion, msg.packagePath).then(() => {
return process.send({result: "loadedCompiler"});
});
}
else if (msg.action === 'compile') {
solcProcess.compile(msg.jsonObj, (err, output) => {
process.send({result: "compilation-" + msg.id, err: err, output: output});
});
}
});

View File

@ -12,6 +12,7 @@ class SolcW {
this.ipc = options.ipc;
this.compilerLoaded = false;
this.solcProcess = null;
this.useDashboard = options.useDashboard;
}
load_compiler(done) {
@ -39,30 +40,31 @@ class SolcW {
logger: self.logger,
events: self.events
});
this.solcProcess.send({action: "init", options: {}});
this.solcProcess.once('result', 'loadedCompiler', () => {
this.solcProcess.once("result", "initiated", () => {
this.events.request("version:get:solc", function(solcVersion) {
if (solcVersion === currentSolcVersion) {
return self.solcProcess.send({action: 'loadCompiler', requirePath: 'solc'});
}
self.events.request("version:getPackagePath", "solc", solcVersion, function(err, path) {
if (err) {
return done(err);
}
let requirePath = fs.dappPath(path);
self.solcProcess.send({action: 'installAndLoadCompiler', solcVersion: solcVersion, packagePath: requirePath});
});
});
});
this.solcProcess.once("result", "loadedCompiler", () => {
self.compilerLoaded = true;
done();
});
this.solcProcess.send({action: "init", options: {logger: self.logger, showSpinner: !self.useDashboard}});
if (this.ipc.isServer()) {
this.ipc.on('compile', self.compile.bind(this));
}
this.events.request("version:get:solc", function(solcVersion) {
if (solcVersion === currentSolcVersion) {
self.solcProcess.send({action: 'loadCompiler', requirePath: 'solc'});
} else {
self.events.request("version:getPackageLocation", "solc", solcVersion, function(err, location) {
if (err) {
return done(err);
}
let requirePath = fs.dappPath(location);
self.solcProcess.send({action: 'loadCompiler', requirePath: requirePath});
});
}
});
}
isCompilerLoaded() {
@ -77,7 +79,10 @@ class SolcW {
}
this.solcProcess.once('result', 'compilation-' + id, (msg) => {
done(JSON.parse(msg.output));
if(msg.err) {
return done(msg.err);
}
done(null, JSON.parse(msg.output));
});
this.solcProcess.send({action: 'compile', jsonObj: jsonObj, id});

View File

@ -80,6 +80,9 @@ class Swarm {
let currentPIterationVersion = require('../../../package.json').dependencies["p-iteration"];
if (pIterationVersion !== currentPIterationVersion) {
self.events.request("version:getPackageLocation", "p-iteration", pIterationVersion, function(err, location) {
if(err){
return self.logger.error("Error getting package location for p-iteration: " + err);
}
self.embark.registerImportFile("p-iteration", fs.dappPath(location));
});
}

View File

@ -68,6 +68,9 @@ class LibraryManager {
this.embark.events.setCommandHandler('version:getPackageLocation', (libName, version, cb) => {
npm.getPackageVersion(libName, version, cb);
});
this.embark.events.setCommandHandler('version:getPackagePath', (libName, version, cb) => {
cb(null, Npm.getPackagePath(libName, version));
});
}
}

View File

@ -1,82 +1,57 @@
const fs = require('../core/fs.js');
const {PerformanceObserver, performance} = require('perf_hooks');
const PluginManager = require('live-plugin-manager-git-fix').PluginManager;
require('colors');
const _ = require('underscore');
const NpmTimer = require('./npmTimer');
class Npm {
constructor(options) {
this.logger = options.logger;
this._logger = options.logger;
this._packageName = options.packageName;
this._version = options.version;
this._installing = {};
}
static getPackagePath(packageName, version){
return './.embark/versions/' + packageName + '/' + version + '/' + packageName;
}
_isInstalling(packageName, version){
return typeof this._installing[packageName + version] != 'undefined';
}
getPackageVersion(packageName, version, callback) {
let packageDirectory = './.embark/versions/' + packageName + '/' + version + '/';
const packagePath = Npm.getPackagePath(packageName, version);
let manager = new PluginManager({pluginsPath: packageDirectory});
if (fs.existsSync(packageDirectory + packageName)) {
return callback(null, packageDirectory + packageName);
// check if this package already exists in the filesystem
if (fs.existsSync(packagePath)) {
return callback(null, packagePath);
}
this.logger.info(__("Downloading {{packageName}} {{version}}...", {packageName: packageName, version: version}));
const pluginManager = new PluginManager({pluginsPath: './.embark/versions/' + packageName + '/' + version + '/'});
const obsMeasure = new PerformanceObserver((items) => {
let entry;
let strDuration;
// check if we're already installing this package
if(this._isInstalling(packageName, version)){
this._installing[packageName + version].push(callback);
}else{
this._installing[packageName + version] = [callback];
// find any download ongoing measurements we've made
entry = _.last(_.where(items.getEntries(), {name: downloadOngoing}));
if(entry){
// ongoing performance mark
strDuration = __('Still downloading {{packageName}} {{version}}... ({{duration}}ms elapsed)', {packageName: packageName, version: version, duration: entry.duration});
}
else{
// otherwise, find our download complete measurement
entry = _.last(_.where(items.getEntries(), {name: downloadComplete}));
const timer = new NpmTimer({logger: this._logger, packageName: packageName, version: version});
timer.start();
if(entry){
strDuration = __('Finished downloading {{packageName}} {{version}} in {{duration}}ms', {packageName: packageName, version: version, duration: entry.duration});
performance.clearMarks();
}
}
// log our measurement and make it red if it has taken too long
if(entry && strDuration){
if(entry.duration > 4000){
strDuration = strDuration.red;
}
this.logger.info(strDuration);
}
});
obsMeasure.observe({entryTypes: ['measure']});
// define mark and measurement names
let startMark = 'downloadStart' + packageName + version;
let ongoingMark = 'downloadOngoingMark' + packageName + version;
let downloadOngoing = 'downloadOngoing' + packageName + version;
let endMark = 'downloadEnd' + packageName + version;
let downloadComplete = 'downloadComplete' + packageName + version;
// mark our start time
performance.mark(startMark);
// function that continually updates the console to show user that we're downloading a library
let intOngoingDownload = setInterval(
function(){
performance.mark(ongoingMark);
performance.measure(downloadOngoing, startMark, ongoingMark);
}, 750);
// do the package download/install
manager.install(packageName, version).then((result) => {
// stop updating console for ongoing download
clearInterval(intOngoingDownload);
performance.mark(endMark);
performance.measure(downloadComplete, startMark, endMark);
callback(null , result.location);
}).catch(callback);
// do the package download/install
pluginManager.install(packageName, version).then((result) => {
timer.end();
this._installing[packageName + version].forEach((cb) => {
cb(null, result.location);
});
delete this._installing[packageName + version];
}).catch(err => {
this._installing[packageName + version].forEach((cb) => {
cb(err);
});
});
}
}
}

99
lib/versions/npmTimer.js Normal file
View File

@ -0,0 +1,99 @@
const {PerformanceObserver, performance} = require('perf_hooks');
const _ = require('underscore');
require('colors');
const i18n = require('../i18n/i18n.js');
i18n.setOrDetectLocale('en');
class NpmTimer{
constructor(options){
this._logger = (options.logger && typeof options.logger.info == 'function') ? options.logger : console;
this._packageName = options.packageName;
this._version = options.version;
this._showSpinner = options.showSpinner || false;
this._spinnerStyle = options.spinnerStyle || 'dots';
this._interval = options.interval || 750;
// define mark and measurement names
this._startMark = 'downloadStart' + this._packageName + this._version;
this._ongoingMark = 'downloadOngoingMark' + this._packageName + this._version;
this._downloadOngoing = 'downloadOngoing' + this._packageName + this._version;
this._endMark = 'downloadEnd' + this._packageName + this._version;
this._downloadComplete = 'downloadComplete' + this._packageName + this._version;
this.observer.observe({entryTypes: ['measure']});
}
get observer(){
if(typeof this._observer == 'undefined'){
this._observer = new PerformanceObserver((items) => {
let entry;
let strDuration;
// find any download ongoing measurements we've made
entry = _.last(_.where(items.getEntries(), {name: this._downloadOngoing}));
if(entry){
// ongoing performance mark
strDuration = __('Downloading and installing {{packageName}} {{version}}... ({{duration}}ms elapsed)', {packageName: this._packageName, version: this._version, duration: entry.duration});
if(this._spinner) this._spinner.text = strDuration;
}
else{
// otherwise, find our download complete measurement
entry = _.last(_.where(items.getEntries(), {name: this._downloadComplete}));
if(entry){
strDuration = __('Finished downloading and installing {{packageName}} {{version}} in {{duration}}ms', {packageName: this._packageName, version: this._version, duration: entry.duration});
performance.clearMarks();
if(this._spinner) this._spinner.succeed(strDuration);
}
}
// log our measurement and make it red if it has taken too long
if(!this._showSpinner && entry && strDuration){
if(entry.duration > 4000){
strDuration = strDuration.red;
}
this._logger.info(strDuration);
}
});
}
return this._observer;
}
start(){
let self = this;
const strDownloadStart = __("Downloading and installing {{packageName}} {{version}}...", {packageName: this._packageName, version: this._version});
if(this._showSpinner){
const ora = require('ora');
this._spinner = ora({
spinner: this._spinnerStyle,
text: strDownloadStart
}).start();
}else{
this._logger.info(strDownloadStart);
}
// mark our start time
performance.mark(this._startMark);
// function that continually updates the console to show user that we're downloading a library
this._intOngoingDownload = setInterval(
function(){
performance.mark(self._ongoingMark);
performance.measure(self._downloadOngoing, self._startMark, self._ongoingMark);
}, this._interval);
}
end(){
// stop updating console for ongoing download
clearInterval(this._intOngoingDownload);
performance.mark(this._endMark);
performance.measure(this._downloadComplete, this._startMark, this._endMark);
}
}
module.exports = NpmTimer;

6712
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,6 @@
"babel-preset-es2017": "6.24.1",
"babel-preset-react": "^6.24.1",
"bip39": "^2.5.0",
"neo-blessed": "^0.2.0",
"chokidar": "^2.0.3",
"clone-deep": "^4.0.0",
"colors": "^1.1.2",
@ -55,8 +54,10 @@
"ipfs-api": "17.2.4",
"live-plugin-manager-git-fix": "^0.12.1",
"merge": "^1.2.0",
"neo-blessed": "^0.2.0",
"node-http-proxy": "^0.2.3",
"node-ipc": "^9.1.1",
"ora": "^2.1.0",
"os-locale": "^2.1.0",
"p-iteration": "^1.1.7",
"parse-json": "^4.0.0",