Merge pull request #1536 from ethereum/supportSeveralCompiler

Support several compiler
pull/3094/head
yann300 6 years ago committed by GitHub
commit b1e94c0b4e
  1. 7
      src/app.js
  2. 26
      src/app/compiler/compiler-abstract.js
  3. 8
      src/app/debugger/debugger.js
  4. 2
      src/app/panels/righthand-panel.js
  5. 3
      src/app/plugin/pluginAPI.js
  6. 16
      src/app/plugin/pluginManager.js
  7. 77
      src/app/tabs/run-tab.js
  8. 3
      src/multiParamManager.js
  9. 9
      src/recorder.js
  10. 5
      src/universal-dapp.js

@ -396,6 +396,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
var offsetToLineColumnConverter = new OffsetToLineColumnConverter(self._components.compiler.event)
registry.put({api: offsetToLineColumnConverter, name: 'offsettolinecolumnconverter'})
self._components.compilersArtefacts = {} // store all the possible compilation data (key represent a compiler name)
registry.put({api: self._components.compilersArtefacts, name: 'compilersartefacts'})
// ----------------- UniversalDApp -----------------
var udapp = new UniversalDApp({
removable: false,
@ -412,9 +415,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
var txlistener = new Txlistener({
api: {
contracts: function () {
if (self._components.compiler.lastCompilationResult && self._components.compiler.lastCompilationResult.data) {
return self._components.compiler.lastCompilationResult.data.contracts
}
if (self._components.compilersArtefacts['__last']) return self._components.compilersArtefacts['__last'].getContracts()
return null
},
resolveReceipt: function (tx, cb) {

@ -0,0 +1,26 @@
'use strict'
var remixLib = require('remix-lib')
var txHelper = remixLib.execution.txHelper
module.exports = class CompilerAbstract {
constructor (languageversion, data) {
this.languageversion = languageversion
this.data = data
}
getContracts () {
return this.data.contracts
}
getContract (name) {
return txHelper.getContract(name, this.data.contracts)
}
visitContracts (calllback) {
return txHelper.visitContracts(this.data.contracts, calllback)
}
getData () {
return this.data
}
}

@ -17,16 +17,14 @@ function Debugger (container, sourceHighlighter, localRegistry) {
this._deps = {
offsetToLineColumnConverter: this._components.registry.get('offsettolinecolumnconverter').api,
editor: this._components.registry.get('editor').api,
compiler: this._components.registry.get('compiler').api
compiler: this._components.registry.get('compiler').api,
compilersArtefacts: this._components.registry.get('compilersartefacts').api
}
this.debugger = new Ethdebugger(
{
executionContext: executionContext,
compilationResult: () => {
var compilationResult = this._deps.compiler.lastCompilationResult
if (compilationResult) {
return compilationResult.data
}
if (this._deps.compilersArtefacts['__last']) return this._deps.compilersArtefacts['__last'].getData()
return null
}
})

@ -54,6 +54,8 @@ module.exports = class RighthandPanel {
self._deps.udapp
)
self._components.registry.put({api: pluginManager, name: 'pluginmanager'})
var analysisTab = new AnalysisTab(self._components.registry)
analysisTab.event.register('newStaticAnaysisWarningMessage', (msg, settings) => { self._components.compile.addWarning(msg, settings) })

@ -44,6 +44,9 @@ module.exports = (pluginManager, fileProviders, fileManager, compiler, udapp) =>
compiler: {
getCompilationResult: (mod, cb) => {
cb(null, compiler.lastCompilationResult)
},
sendCompilationResult: (mod, file, source, languageVersion, data, cb) => {
pluginManager.receivedDataFrom('sendCompilationResult', mod, [file, source, languageVersion, data])
}
},
udapp: {

@ -1,4 +1,6 @@
'use strict'
var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager
var executionContext = require('../../execution-context')
const PluginAPI = require('./pluginAPI')
/**
@ -80,6 +82,7 @@ const PluginAPI = require('./pluginAPI')
module.exports = class PluginManager {
constructor (app, compiler, txlistener, fileProviders, fileManager, udapp) {
const self = this
self.event = new EventManager()
var pluginAPI = new PluginAPI(
this,
fileProviders,
@ -90,6 +93,14 @@ module.exports = class PluginManager {
self.plugins = {}
self.origins = {}
self.inFocus
fileManager.event.register('currentFileChanged', (file, provider) => {
self.broadcast(JSON.stringify({
action: 'notification',
key: 'editor',
type: 'currentFileChanged',
value: [ file ]
}))
})
compiler.event.register('compilationFinished', (success, data, source) => {
self.broadcast(JSON.stringify({
action: 'notification',
@ -184,6 +195,11 @@ module.exports = class PluginManager {
this.post(this.origins[origin], value)
}
}
receivedDataFrom (methodName, mod, argumentsArray) {
// TODO check whether 'mod' as right to do that
console.log(argumentsArray)
this.event.trigger(methodName, argumentsArray)
}
post (name, value) {
const self = this
if (self.plugins[name]) {

@ -21,6 +21,7 @@ var addTooltip = require('../ui/tooltip')
var css = require('./styles/run-tab-styles')
var MultiParamManager = require('../../multiParamManager')
var modalDialog = require('../ui/modaldialog')
var CompilerAbstract = require('../compiler/compiler-abstract')
function runTab (opts, localRegistry) {
/* -------------------------
@ -76,7 +77,9 @@ function runTab (opts, localRegistry) {
fileManager: self._components.registry.get('filemanager').api,
editor: self._components.registry.get('editor').api,
logCallback: self._components.registry.get('logCallback').api,
filePanel: self._components.registry.get('filepanel').api
filePanel: self._components.registry.get('filepanel').api,
pluginManager: self._components.registry.get('pluginmanager').api,
compilersArtefacts: self._components.registry.get('compilersartefacts').api
}
self._deps.udapp.resetAPI(self._components.transactionContextAPI)
self._view.recorderCount = yo`<span>0</span>`
@ -193,7 +196,7 @@ function updateAccountBalances (container, self) {
RECORDER
------------------------------------------------ */
function makeRecorder (registry, runTabEvent, self) {
var recorder = new Recorder(self._deps.compiler, self._deps.udapp, self._deps.logCallback)
var recorder = new Recorder(self._deps.udapp, self._deps.logCallback)
recorder.event.register('newTxRecorded', (count) => {
self.data.count = count
@ -293,8 +296,9 @@ function contractDropdown (events, self) {
instanceContainer.appendChild(self._view.noInstancesText)
var compFails = yo`<i title="Contract compilation failed. Please check the compile tab for more information." class="fa fa-times-circle ${css.errorIcon}" ></i>`
var info = yo`<i class="fa fa-info ${css.infoDeployAction}" aria-hidden="true" title="*.sol files allows deploying and accessing contracts. *.abi files only allows accessing contracts."></i>`
self._deps.compiler.event.register('compilationFinished', function (success, data, source) {
getContractNames(success, data)
var newlyCompiled = (success, data, source, compiler, compilerFullName) => {
getContractNames(success, data, compiler, compilerFullName)
if (success) {
compFails.style.display = 'none'
document.querySelector(`.${css.contractNames}`).classList.remove(css.contractNamesError)
@ -302,6 +306,22 @@ function contractDropdown (events, self) {
compFails.style.display = 'block'
document.querySelector(`.${css.contractNames}`).classList.add(css.contractNamesError)
}
}
self._deps.pluginManager.event.register('sendCompilationResult', (file, source, languageVersion, data) => {
// TODO check whether the tab is configured
let compiler = new CompilerAbstract(languageVersion, data)
self._deps.compilersArtefacts[languageVersion] = compiler
self._deps.compilersArtefacts['__last'] = compiler
newlyCompiled(true, data, source, compiler, languageVersion)
})
self._deps.compiler.event.register('compilationFinished', (success, data, source) => {
var name = 'solidity'
let compiler = new CompilerAbstract(name, data)
self._deps.compilersArtefacts[name] = compiler
self._deps.compilersArtefacts['__last'] = compiler
newlyCompiled(success, data, source, self._deps.compiler, name)
})
var deployAction = (value) => {
@ -327,11 +347,16 @@ function contractDropdown (events, self) {
var selectContractNames = yo`<select class="${css.contractNames}" disabled></select>`
function getSelectedContract () {
var contractName = selectContractNames.children[selectContractNames.selectedIndex].innerHTML
var contract = selectContractNames.children[selectContractNames.selectedIndex]
var contractName = contract.innerHTML
var compiler = self._deps.compilersArtefacts[contract.getAttribute('compiler')]
if (!compiler) return null
if (contractName) {
return {
name: contractName,
contract: self._deps.compiler.getContract(contractName)
contract: compiler.getContract(contractName),
compiler
}
}
return null
@ -357,11 +382,12 @@ function contractDropdown (events, self) {
function setInputParamsPlaceHolder () {
self._view.createPanel.innerHTML = ''
if (self._deps.compiler.getContract && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) {
var ctrabi = txHelper.getConstructorInterface(getSelectedContract().contract.object.abi)
var ctrEVMbc = getSelectedContract().contract.object.evm.bytecode.object
if (selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) {
var selectedContract = getSelectedContract()
var ctrabi = txHelper.getConstructorInterface(selectedContract.contract.object.abi)
var ctrEVMbc = selectedContract.contract.object.evm.bytecode.object
var createConstructorInstance = new MultiParamManager(0, ctrabi, (valArray, inputsValues) => {
createInstance(inputsValues)
createInstance(inputsValues, selectedContract.compiler)
}, txHelper.inputParametersDeclarationToString(ctrabi.inputs), 'Deploy', ctrEVMbc)
self._view.createPanel.appendChild(createConstructorInstance.render())
return
@ -372,9 +398,12 @@ function contractDropdown (events, self) {
selectContractNames.addEventListener('change', setInputParamsPlaceHolder)
function createInstanceCallback (error, selectedContract, data) {
if (error) return self._deps.logCallback(`creation of ${selectedContract.name} errored: ` + error)
function createInstanceCallback (selectedContract, data) {
self._deps.logCallback(`creation of ${selectedContract.name} pending...`)
if (data) {
data.contractName = selectedContract.name
data.linkReferences = selectedContract.contract.object.evm.bytecode.linkReferences
}
self._deps.udapp.createContract(data, (error, txResult) => {
if (!error) {
var isVM = executionContext.isVM()
@ -400,7 +429,7 @@ function contractDropdown (events, self) {
}
// DEPLOY INSTANCE
function createInstance (args) {
function createInstance (args, compiler) {
var selectedContract = getSelectedContract()
if (selectedContract.contract.object.evm.bytecode.object.length === 0) {
@ -413,8 +442,9 @@ function contractDropdown (events, self) {
self._deps.filePanel.compilerMetadata().metadataOf(selectedContract.name, (error, contractMetadata) => {
if (error) return self._deps.logCallback(`creation of ${selectedContract.name} errored: ` + error)
if (!contractMetadata || (contractMetadata && contractMetadata.autoDeployLib)) {
txFormat.buildData(selectedContract.name, selectedContract.contract.object, self._deps.compiler.getContracts(), true, constructor, args, (error, data) => {
createInstanceCallback(error, selectedContract, data)
txFormat.buildData(selectedContract.name, selectedContract.contract.object, compiler.getContracts(), true, constructor, args, (error, data) => {
if (error) return self._deps.logCallback(`creation of ${selectedContract.name} errored: ` + error)
createInstanceCallback(selectedContract, data)
}, (msg) => {
self._deps.logCallback(msg)
}, (data, runTxCallback) => {
@ -424,14 +454,14 @@ function contractDropdown (events, self) {
} else {
if (Object.keys(selectedContract.contract.object.evm.bytecode.linkReferences).length) self._deps.logCallback(`linking ${JSON.stringify(selectedContract.contract.object.evm.bytecode.linkReferences, null, '\t')} using ${JSON.stringify(contractMetadata.linkReferences, null, '\t')}`)
txFormat.encodeConstructorCallAndLinkLibraries(selectedContract.contract.object, args, constructor, contractMetadata.linkReferences, selectedContract.contract.object.evm.bytecode.linkReferences, (error, data) => {
if (data) data.contractName = selectedContract.name
createInstanceCallback(error, selectedContract, data)
if (error) return self._deps.logCallback(`creation of ${selectedContract.name} errored: ` + error)
createInstanceCallback(selectedContract, data)
})
}
})
}
if (selectedContract.contract.object.evm.deployedBytecode.object.length / 2 > 24576) {
if (selectedContract.contract.object.evm.deployedBytecode && selectedContract.contract.object.evm.deployedBytecode.object.length / 2 > 24576) {
modalDialog('Contract code size over limit', yo`<div>Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fails. <br>
More info: <a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md" target="_blank">eip-170</a>
</div>`,
@ -454,7 +484,6 @@ function contractDropdown (events, self) {
function loadFromAddress () {
var noInstancesText = self._view.noInstancesText
if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) }
var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
var address = atAddressButtonInput.value
if (!ethJSUtil.isValidAddress(address)) {
return modalDialogCustom.alert('Invalid address.')
@ -473,19 +502,19 @@ function contractDropdown (events, self) {
instanceContainer.appendChild(self._deps.udappUI.renderInstanceFromABI(abi, address, address))
})
} else {
var contract = self._deps.compiler.getContract(contractNames.children[contractNames.selectedIndex].innerHTML)
instanceContainer.appendChild(self._deps.udappUI.renderInstance(contract.object, address, selectContractNames.value))
var selectedContract = getSelectedContract()
instanceContainer.appendChild(self._deps.udappUI.renderInstance(selectedContract.contract.object, address, selectContractNames.value))
}
}
// GET NAMES OF ALL THE CONTRACTS
function getContractNames (success, data) {
function getContractNames (success, data, compiler, compilerFullName) {
var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
contractNames.innerHTML = ''
if (success) {
selectContractNames.removeAttribute('disabled')
self._deps.compiler.visitContracts((contract) => {
contractNames.appendChild(yo`<option value="${contract.name}">${contract.name}</option>`)
compiler.visitContracts((contract) => {
contractNames.appendChild(yo`<option compiler="${compilerFullName}">${contract.name}</option>`)
})
} else {
selectContractNames.setAttribute('disabled', true)

@ -183,6 +183,9 @@ class MultiParamManager {
if (this.funABI.inputs && this.funABI.inputs.length > 0) {
contractProperty.classList.add(css.hasArgs)
} else if (this.funABI.type === 'fallback') {
contractProperty.classList.add(css.hasArgs)
this.contractActionsContainerSingle.querySelector('i').style.visibility = 'hidden'
} else {
this.contractActionsContainerSingle.querySelector('i').style.visibility = 'hidden'
this.basicInputField.style.display = 'none'

@ -13,7 +13,7 @@ var modal = require('./app/ui/modal-dialog-custom')
*
*/
class Recorder {
constructor (compiler, udapp, logCallBack) {
constructor (udapp, logCallBack) {
var self = this
self.logCallBack = logCallBack
self.event = new EventManager()
@ -27,14 +27,12 @@ class Recorder {
if (this.data._listen) {
var record = { value, parameters: payLoad.funArgs }
if (!to) {
var selectedContract = compiler.getContract(payLoad.contractName)
if (selectedContract) {
var abi = selectedContract.object.abi
var abi = payLoad.contractABI
var sha3 = ethutil.bufferToHex(ethutil.sha3(abi))
record.abi = sha3
record.contractName = payLoad.contractName
record.bytecode = payLoad.contractBytecode
record.linkReferences = selectedContract.object.evm.bytecode.linkReferences
record.linkReferences = payLoad.linkReferences
if (record.linkReferences && Object.keys(record.linkReferences).length) {
for (var file in record.linkReferences) {
for (var lib in record.linkReferences[file]) {
@ -45,7 +43,6 @@ class Recorder {
self.data._abis[sha3] = abi
this.data._contractABIReferences[timestamp] = sha3
}
} else {
var creationTimestamp = this.data._createdContracts[to]
record.to = `created{${creationTimestamp}}`

@ -205,7 +205,7 @@ UniversalDApp.prototype.call = function (isUserAction, args, value, lookupOnly,
}
}
// contractsDetails is used to resolve libraries
txFormat.buildData(args.contractName, args.contractAbi, self.data.contractsDetails, false, args.funABI, value, (error, data) => {
txFormat.buildData(args.contractName, args.contractAbi, self.data.contractsDetails, false, args.funABI, args.funABI.type !== 'fallback' ? value : '', (error, data) => {
if (!error) {
if (isUserAction) {
if (!args.funABI.constant) {
@ -214,6 +214,7 @@ UniversalDApp.prototype.call = function (isUserAction, args, value, lookupOnly,
self._deps.logCallback(`${logMsg}`)
}
}
if (args.funABI.type === 'fallback') data.dataHex = value
self.callFunction(args.address, data, args.funABI, (error, txResult) => {
if (!error) {
var isVM = executionContext.isVM()
@ -349,7 +350,7 @@ UniversalDApp.prototype.runTx = function (args, cb) {
},
function runTransaction (fromAddress, value, gasLimit, next) {
var tx = { to: args.to, data: args.data.dataHex, useCall: args.useCall, from: fromAddress, value: value, gasLimit: gasLimit }
var payLoad = { funAbi: args.data.funAbi, funArgs: args.data.funArgs, contractBytecode: args.data.contractBytecode, contractName: args.data.contractName }
var payLoad = { funAbi: args.data.funAbi, funArgs: args.data.funArgs, contractBytecode: args.data.contractBytecode, contractName: args.data.contractName, contractABI: args.data.contractABI, linkReferences: args.data.linkReferences }
var timestamp = Date.now()
self.event.trigger('initiatingTransaction', [timestamp, tx, payLoad])

Loading…
Cancel
Save