From a91c94dc49f8a8d44a577bb43f91ebf95cea6ba8 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 27 Jun 2018 11:51:29 +0200 Subject: [PATCH 1/8] fix terminal api --- src/app/panels/terminal.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/app/panels/terminal.js b/src/app/panels/terminal.js index 25b2c01c74..1c794be37a 100644 --- a/src/app/panels/terminal.js +++ b/src/app/panels/terminal.js @@ -579,5 +579,13 @@ function domTerminalFeatures (self, scopedCommands) { } function blockify (el) { return yo`
${el}
` } +<<<<<<< HEAD +======= +// PENDING TX +function updatePendingTxs (udapp, el) { + var count = Object.keys(udapp.pendingTransactions()).length + el.innerText = count +} +>>>>>>> fix terminal api module.exports = Terminal From 06e81ca845080c90f0157592f60ba550d5256145 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Jul 2018 21:17:29 +0200 Subject: [PATCH 2/8] add basic plugin API --- src/app.js | 8 ++++ src/app/panels/righthand-panel.js | 41 +++++++++++++--- src/app/plugin/plugin.md | 41 ++++++++++++++++ src/app/plugin/pluginAPI.js | 50 ++++++++++++++++--- src/app/plugin/pluginManager.js | 80 +++++++++++++++++++------------ src/app/tabs/plugin-tab.js | 5 +- src/app/tabs/tabbed-menu.js | 13 ++++- src/universal-dapp.js | 23 +++++++++ test-browser/plugin/remix.js | 45 ++++++++++++++++- 9 files changed, 257 insertions(+), 49 deletions(-) create mode 100644 src/app/plugin/plugin.md diff --git a/src/app.js b/src/app.js index 84e96b14bf..6186455d3c 100644 --- a/src/app.js +++ b/src/app.js @@ -578,6 +578,14 @@ Please make a backup of your contracts and start using http://remix.ethereum.org if (queryParams.get().debugtx) { self.startdebugging(queryParams.get().debugtx) } + + if (queryParams.get().pluginurl) { + var title = queryParams.get().plugintitle + var url = queryParams.get().pluginurl + modalDialogCustom.confirm(null, `Remix is going to load the extension "${title}" located at ${queryParams.get().pluginurl}. Are you sure to load this external extension?`, () => { + self._components.righthandpanel.loadPlugin({title, url}) + }) + } }) // chrome app diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index c93c8902bb..35a78ddb16 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -15,6 +15,7 @@ const SupportTab = require('../tabs/support-tab') const PluginTab = require('../tabs/plugin-tab') const TestTab = require('../tabs/test-tab') const RunTab = require('../tabs/run-tab') +const PluginAPI = require('../plugin/pluginAPI') const EventManager = remixLib.EventManager const styles = styleguide.chooser() @@ -24,6 +25,7 @@ module.exports = class RighthandPanel { const self = this self._components = {} self._components.registry = localRegistry || globalRegistry + self._components.registry.put({api: this, name: 'righthandpanel'}) self.event = new EventManager() self._view = { element: null, @@ -32,11 +34,32 @@ module.exports = class RighthandPanel { dragbar: null } - self._components.registry.put({api: this, name: 'righthandpanel'}) + self._deps = { + fileProviders: self._components.registry.get('fileproviders').api, + compiler: self._components.registry.get('compiler').api, + udapp: self._components.registry.get('udapp').api, + app: self._components.registry.get('app').api, + txlistener: self._components.registry.get('txlistener').api + } + + var tabbedMenu = new TabbedMenu(self._components.registry) + + var pluginAPI = new PluginAPI( + self._deps.fileProviders, + self._deps.compiler, + self._deps.udapp, + tabbedMenu + ) + + var pluginManager = new PluginManager( + pluginAPI, + self._deps.app, + self._deps.compiler, + self._deps.txlistener) self._components = { - pluginManager: new PluginManager(self._components.registry), - tabbedMenu: new TabbedMenu(self._components.registry), + pluginManager: pluginManager, + tabbedMenu: tabbedMenu, compile: new CompileTab(self._components.registry), run: new RunTab(self._components.registry), settings: new SettingsTab(self._components.registry), @@ -47,12 +70,16 @@ module.exports = class RighthandPanel { } self.event.register('plugin-loadRequest', json => { - const tab = new PluginTab({}, self._events, json) - const content = tab.render() - self._components.tabbedMenu.addTab(json.title, 'plugin', content) - self._components.pluginManager.register(json, content) + self.loadPlugin(json) }) + self.loadPlugin = function (json) { + var tab = new PluginTab(json) + var content = tab.render() + self._components.tabbedMenu.addTab(json.title, json.title + ' plugin', content) + self.pluginManager.register(json, content) + } + self._view.dragbar = yo`
` self._view.element = yo`
diff --git a/src/app/plugin/plugin.md b/src/app/plugin/plugin.md new file mode 100644 index 0000000000..2d39655b49 --- /dev/null +++ b/src/app/plugin/plugin.md @@ -0,0 +1,41 @@ +plugin api + +# current APIs: + +## 1) notifications + +### app (key: app) + + - unfocus `[]` + - focus `[]` + +### compiler (key: compiler) + + - compilationFinished `[success (bool), data (obj), source (obj)]` + - compilationData `[compilationResult]` + +### transaction listener (key: txlistener) + + - newTransaction `tx (obj)` + +## 2) interactions + +### app + + - getExecutionContextProvider `@return {String} provider (injected | web3 | vm)` + - updateTitle `@param {String} title` + +### config + + - setConfig `@param {String} path, @param {String} content` + - getConfig `@param {String} path` + - removeConfig `@param {String} path` + +### compiler + - getCompilationResult `@return {Object} compilation result` + +### udapp (only VM) + - runTx `@param {Object} tx` + - getAccounts `@return {Array} acccounts` + - createVMAccount `@param {String} privateKey, @param {String} balance (hex)` + \ No newline at end of file diff --git a/src/app/plugin/pluginAPI.js b/src/app/plugin/pluginAPI.js index 79bea002e0..0036e8b873 100644 --- a/src/app/plugin/pluginAPI.js +++ b/src/app/plugin/pluginAPI.js @@ -1,26 +1,62 @@ 'use strict' +var executionContext = require('../../execution-context') + /* Defines available API. `key` / `type` */ -module.exports = (registry) => { +module.exports = (fileProviders, compiler, udapp, tabbedMenu) => { return { + app: { + getExecutionContextProvider: (mod, cb) => { + cb(null, executionContext.getProvider()) + }, + updateTitle: (mod, title, cb) => { + tabbedMenu.updateTabTitle(mod, title) + } + }, config: { setConfig: (mod, path, content, cb) => { - registry.get('fileproviders/config').api.set(mod + '/' + path, content) + fileProviders['config'].set(mod + '/' + path, content) cb() }, getConfig: (mod, path, cb) => { - cb(null, registry.get('fileproviders/config').get(mod + '/' + path)) + cb(null, fileProviders['config'].get(mod + '/' + path)) }, removeConfig: (mod, path, cb) => { - cb(null, registry.get('fileproviders/config').api.remove(mod + '/' + path)) + cb(null, fileProviders['config'].remove(mod + '/' + path)) if (cb) cb() } }, compiler: { - getCompilationResult: () => { - return registry.get('compiler').api.lastCompilationResult + getCompilationResult: (mod, cb) => { + cb(null, compiler.lastCompilationResult) + } + }, + udapp: { + runTx: (mod, tx, cb) => { + if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow sending a transaction through a web3 connection. Only vm mode is allowed') + udapp.silentRunTx(tx, (error, result) => { + if (error) return cb(error) + cb(null, { + transactionHash: result.transactionHash, + status: result.result.status, + gasUsed: '0x' + result.result.gasUsed.toString('hex'), + error: result.result.vm.exceptionError, + return: result.result.vm.return ? '0x' + result.result.vm.return.toString('hex') : '0x', + createdAddress: result.result.createdAddress ? '0x' + result.result.createdAddress.toString('hex') : undefined + }) + }) + }, + getAccounts: (mod, cb) => { + if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow retrieving accounts through a web3 connection. Only vm mode is allowed') + udapp.getAccounts(cb) + }, + createVMAccount: (mod, privateKey, balance, cb) => { + if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed') + udapp.createVMAccount(privateKey, balance, (error, address) => { + cb(error, address) + }) } } } -} +} \ No newline at end of file diff --git a/src/app/plugin/pluginManager.js b/src/app/plugin/pluginManager.js index 462b457ea1..88c94df0dc 100644 --- a/src/app/plugin/pluginManager.js +++ b/src/app/plugin/pluginManager.js @@ -1,7 +1,5 @@ 'use strict' - -var globalRegistry = require('../../global/registry') -var PluginAPI = require('./pluginAPI') +var executionContext = require('../../execution-context') /** * Register and Manage plugin: * @@ -79,19 +77,13 @@ var PluginAPI = require('./pluginAPI') * */ module.exports = class PluginManager { - constructor (localRegistry) { + constructor (pluginAPI, app, compiler, txlistener) { const self = this self.plugins = {} - self._components = {} - self._components.registry = localRegistry || globalRegistry - self._components.pluginAPI = new PluginAPI(self._components.registry) - self._deps = { - compiler: self._components.registry.get('compiler').api, - app: self._components.registry.get('app').api - } + self.origins = {} self.inFocus self.allowedapi = {'setConfig': 1, 'getConfig': 1, 'removeConfig': 1} - self._deps.compiler.event.register('compilationFinished', (success, data, source) => { + compiler.event.register('compilationFinished', (success, data, source) => { if (self.inFocus) { // trigger to the current focus self.post(self.inFocus, JSON.stringify({ @@ -103,7 +95,17 @@ module.exports = class PluginManager { } }) - self._deps.app.event.register('tabChanged', (tabName) => { + txlistener.event.register('newTransaction', (tx) => { + if (executionContext.getProvider() !== 'vm') return + self.broadcast(JSON.stringify({ + action: 'notification', + key: 'txlistener', + type: 'newTransaction', + value: [tx] + })) + }) + + app.event.register('tabChanged', (tabName) => { if (self.inFocus && self.inFocus !== tabName) { // trigger unfocus self.post(self.inFocus, JSON.stringify({ @@ -122,18 +124,25 @@ module.exports = class PluginManager { value: [] })) self.inFocus = tabName - self.post(tabName, JSON.stringify({ - action: 'notification', - key: 'compiler', - type: 'compilationData', - value: [self._deps.compiler.getCompilationResult()] - })) + pluginAPI.compiler.getCompilationResult(tabName, (error, data) => { + if (!error) return + self.post(tabName, JSON.stringify({ + action: 'notification', + key: 'compiler', + type: 'compilationData', + value: [data] + })) + }) } }) window.addEventListener('message', (event) => { + if (event.type !== 'message') return + var extension = self.origins[event.origin] + if (!extension) return + function response (key, type, callid, error, result) { - self.post(self.inFocus, JSON.stringify({ + self.postToOrigin(event.origin, JSON.stringify({ id: callid, action: 'response', key: key, @@ -142,21 +151,30 @@ module.exports = class PluginManager { value: [ result ] })) } - if (event.type === 'message' && self.inFocus && self.plugins[self.inFocus] && self.plugins[self.inFocus].origin === event.origin) { - var data = JSON.parse(event.data) - data.value.unshift(self.inFocus) - if (self.allowedapi[data.type]) { - data.value.push((error, result) => { - response(data.key, data.type, data.id, error, result) - }) - self._components.pluginAPI[data.key][data.type].apply({}, data.value) - } - } + var data = JSON.parse(event.data) + data.value.unshift(extension) + // if (self.allowedapi[data.type]) { + data.value.push((error, result) => { + response(data.key, data.type, data.id, error, result) + }) + pluginAPI[data.key][data.type].apply({}, data.value) + // } }, false) } register (desc, content) { const self = this self.plugins[desc.title] = {content, origin: desc.url} + self.origins[desc.url] = desc.title + } + broadcast (value) { + for (var plugin in this.plugins) { + this.post(plugin, value) + } + } + postToOrigin (origin, value) { + if (this.origins[origin]) { + this.post(this.origins[origin], value) + } } post (name, value) { const self = this @@ -164,4 +182,4 @@ module.exports = class PluginManager { self.plugins[name].content.querySelector('iframe').contentWindow.postMessage(value, self.plugins[name].origin) } } -} +} \ No newline at end of file diff --git a/src/app/tabs/plugin-tab.js b/src/app/tabs/plugin-tab.js index d4ad06924c..ae5360792e 100644 --- a/src/app/tabs/plugin-tab.js +++ b/src/app/tabs/plugin-tab.js @@ -6,10 +6,11 @@ var globalRegistry = require('../../global/registry') var EventManager = remixLib.EventManager module.exports = class plugintab { - constructor (localRegistry) { + constructor (json, localRegistry) { const self = this self.event = new EventManager() self._view = { el: null } + self.data = { json } self._components = {} self._components.registry = localRegistry || globalRegistry } @@ -18,7 +19,7 @@ module.exports = class plugintab { if (self._view.el) return self._view.el self._view.el = yo`
- +
` return self._view.el } diff --git a/src/app/tabs/tabbed-menu.js b/src/app/tabs/tabbed-menu.js index bfb3b6b102..ca9f39de28 100644 --- a/src/app/tabs/tabbed-menu.js +++ b/src/app/tabs/tabbed-menu.js @@ -46,13 +46,24 @@ module.exports = class TabbedMenu { if (self._view.el) self._view.el.appendChild(self._view.tabs[title]) if (self._view.viewport) self._view.viewport.appendChild(self._view.contents[title]) } + getTabByClass (tabClass) { + const self = this + return self._view.el.querySelector(`li.${tabClass}`) + } + updateTabTitle (tabClass, title) { + const self = this + var tab = self.getTabByClass(tabClass) + if (tab) tab.innerHTML = title + } selectTabByTitle (title) { const self = this self.selectTab(self._view.tabs[title]) } selectTabByClassName (tabClass) { const self = this - self.selectTab(self._view.el.querySelector(`li.${tabClass}`)) + var tab = self.getTabByClass(tabClass) + if (tab) self.selectTab(tab) + return tab } selectTab (el) { const self = this diff --git a/src/universal-dapp.js b/src/universal-dapp.js index 48b9fc2829..5cd70814d7 100644 --- a/src/universal-dapp.js +++ b/src/universal-dapp.js @@ -80,6 +80,12 @@ UniversalDApp.prototype.resetAPI = function (transactionContextAPI) { this.transactionContextAPI = transactionContextAPI } +UniversalDApp.prototype.createVMAccount = function (privateKey, balance, cb) { + this._addAccount(privateKey, balance) + privateKey = new Buffer(privateKey, 'hex') + cb(null, '0x' + ethJSUtil.privateToAddress(privateKey).toString('hex')) +} + UniversalDApp.prototype.newAccount = function (password, cb) { if (!executionContext.isVM()) { if (!this._deps.config.get('settings/personal-mode')) { @@ -282,6 +288,23 @@ UniversalDApp.prototype.getInputs = function (funABI) { return txHelper.inputParametersDeclarationToString(funABI.inputs) } +/** + * This function send a tx without alerting the user (if mainnet or if gas estimation too high). + * SHOULD BE TAKEN CAREFULLY! + * + * @param {Object} tx - transaction. + * @param {Function} callback - callback. + */ +UniversalDApp.prototype.silentRunTx = function (tx, cb) { + if (!executionContext.isVM()) return cb('Cannot silently send transaction through a web3 provider') + this.txRunner.rawRun( + tx, + (network, tx, gasEstimation, continueTxExecution, cancelCb) => { continueTxExecution() }, + (error, continueTxExecution, cancelCb) => { if (error) { cb(error) } else { continueTxExecution() } }, + (okCb, cancelCb) => { okCb() }, + cb) +} + UniversalDApp.prototype.runTx = function (args, cb) { const self = this async.waterfall([ diff --git a/test-browser/plugin/remix.js b/test-browser/plugin/remix.js index b9984ea646..fe16c56cb6 100644 --- a/test-browser/plugin/remix.js +++ b/test-browser/plugin/remix.js @@ -1,4 +1,17 @@ +/* +test contract creation +*/ +var addrResolverByteCode = '0x6060604052341561000f57600080fd5b33600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061033c8061005f6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806338cc483114610067578063767800de146100bc578063a6f9dae114610111578063d1d80fdf1461014a575b600080fd5b341561007257600080fd5b61007a610183565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100c757600080fd5b6100cf6101ac565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561011c57600080fd5b610148600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101d1565b005b341561015557600080fd5b610181600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610271565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022d57600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156102cd57600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505600a165627a7a723058201b23355f578cb9a23c0a43a440ab2631b62df7be0a8e759812a70f01344224da0029' + +const addrResolverTx = { + gasLimit: '0x2710', + from: '0xca35b7d915458ef540ade6068dfe2f44e8fa733c', + data: addrResolverByteCode, + value: '0x00', + useCall: false +} + function receiveMessage (event) { console.log('receiveMessage', event.data, event.source, event.origin) document.getElementById('compilationdata').innerHTML += event.data + '
' @@ -35,4 +48,34 @@ window.onload = function () { id: 36 }), '*') }) -} + + document.querySelector('input#testcontractcreation').addEventListener('click', function () { + window.parent.postMessage(JSON.stringify({ + action: 'request', + key: 'udapp', + type: 'runTx', + value: [addrResolverTx], + id: 37 + }), '*') + }) + + document.querySelector('input#testaccountcreation').addEventListener('click', function () { + window.parent.postMessage(JSON.stringify({ + action: 'request', + key: 'udapp', + type: 'createVMAccount', + value: ['71975fbf7fe448e004ac7ae54cad0a383c3906055a75468714156a07385e96ce', '0x56BC75E2D63100000'], + id: 38 + }), '*') + }) + var k = 0 + document.querySelector('input#testchangetitle').addEventListener('click', function () { + window.parent.postMessage(JSON.stringify({ + action: 'request', + key: 'app', + type: 'updateTitle', + value: ['changed title ' + k++], + id: 39 + }), '*') + }) +} \ No newline at end of file From 3840aee8c9bd85b3d5e16896998e413353d9e7b1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Jul 2018 21:57:21 +0200 Subject: [PATCH 3/8] fix pluginmanager --- src/app/panels/righthand-panel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index 35a78ddb16..77f389f278 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -77,7 +77,7 @@ module.exports = class RighthandPanel { var tab = new PluginTab(json) var content = tab.render() self._components.tabbedMenu.addTab(json.title, json.title + ' plugin', content) - self.pluginManager.register(json, content) + self._components.pluginManager.register(json, content) } self._view.dragbar = yo`
` From b75dd57a0978d6d90a6e703a6d5747eb02e884e5 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Jul 2018 21:57:32 +0200 Subject: [PATCH 4/8] fix offsetToLineColumn --- src/app/debugger/debugger.js | 6 +++--- src/app/editor/contextView.js | 2 +- src/app/editor/contextualListener.js | 2 +- src/app/staticanalysis/staticAnalysisView.js | 5 ++++- src/lib/offsetToLineColumnConverter.js | 6 +++--- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/app/debugger/debugger.js b/src/app/debugger/debugger.js index 57a9ebaeed..8d3e39a764 100644 --- a/src/app/debugger/debugger.js +++ b/src/app/debugger/debugger.js @@ -36,7 +36,7 @@ function Debugger (id, sourceHighlighter, localRegistry) { this.isActive = false this.breakPointManager = new remixCore.code.BreakpointManager(this.debugger, (sourceLocation) => { - return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, this._deps.compiler.lastCompilationResult.data) + return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, this._deps.compiler.lastCompilationResult.source.sources) }) this.debugger.setBreakpointManager(this.breakPointManager) @@ -74,8 +74,8 @@ function Debugger (id, sourceHighlighter, localRegistry) { this.debugger.codeManager.event.register('changed', this, function (code, address, index) { if (self._deps.compiler.lastCompilationResult) { self.debugger.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, index, self._deps.compiler.lastCompilationResult.data.contracts, function (error, rawLocation) { - if (!error) { - var lineColumnPos = self._deps.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, self._deps.compiler.lastCompilationResult) + if (!error && self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) { + var lineColumnPos = self._deps.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, self._deps.compiler.lastCompilationResult.source.sources) self._components.sourceHighlighter.currentSourceLocation(lineColumnPos, rawLocation) } else { self._components.sourceHighlighter.currentSourceLocation(null) diff --git a/src/app/editor/contextView.js b/src/app/editor/contextView.js index c9200ed0b8..e4781f6b68 100644 --- a/src/app/editor/contextView.js +++ b/src/app/editor/contextView.js @@ -98,7 +98,7 @@ class ContextView { } } if (self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) { - var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult) + var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult.source.sources) var filename = self._deps.compiler.getSourceName(position.file) // TODO: refactor with rendererAPI.errorClick if (filename !== self._deps.config.get('currentFile')) { diff --git a/src/app/editor/contextualListener.js b/src/app/editor/contextualListener.js index 103b0349d8..d55965fd49 100644 --- a/src/app/editor/contextualListener.js +++ b/src/app/editor/contextualListener.js @@ -114,7 +114,7 @@ class ContextualListener { _highlightInternal (position, node) { var self = this if (self._deps.compiler.lastCompilationResult && self._deps.compiler.lastCompilationResult.data) { - var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult) + var lineColumn = self._deps.offsetToLineColumnConverter.offsetToLineColumn(position, position.file, self._deps.compiler.lastCompilationResult.source.sources) var css = 'highlightreference' if (node.children && node.children.length) { // If node has children, highlight the entire line. if not, just highlight the current source position of the node. diff --git a/src/app/staticanalysis/staticAnalysisView.js b/src/app/staticanalysis/staticAnalysisView.js index fb50a95080..ae68a79e73 100644 --- a/src/app/staticanalysis/staticAnalysisView.js +++ b/src/app/staticanalysis/staticAnalysisView.js @@ -20,6 +20,7 @@ function staticAnalysisView (localRegistry) { this.runner = new StaticAnalysisRunner() this.modulesView = renderModules(this.runner.modules()) this.lastCompilationResult = null + this.lastCompilationSource = null self._components = {} self._components.registry = localRegistry || globlalRegistry // dependencies @@ -31,9 +32,11 @@ function staticAnalysisView (localRegistry) { self._deps.compiler.event.register('compilationFinished', function (success, data, source) { self.lastCompilationResult = null + self.lastCompilationSource = null $('#staticanalysisresult').empty() if (success) { self.lastCompilationResult = data + self.lastCompilationSource = source if (self.view.querySelector('#autorunstaticanalysis').checked) { self.run() } @@ -94,7 +97,7 @@ staticAnalysisView.prototype.run = function () { start: parseInt(split[0]), length: parseInt(split[1]) } - location = self._deps.offsetToLineColumnConverter.offsetToLineColumn(location, file) + location = self._deps.offsetToLineColumnConverter.offsetToLineColumn(location, file, self.lastCompilationSource.sources) location = Object.keys(self.lastCompilationResult.contracts)[file] + ':' + (location.start.line + 1) + ':' + (location.start.column + 1) + ':' } warningCount++ diff --git a/src/lib/offsetToLineColumnConverter.js b/src/lib/offsetToLineColumnConverter.js index f31fa68977..2a73dfbe6f 100644 --- a/src/lib/offsetToLineColumnConverter.js +++ b/src/lib/offsetToLineColumnConverter.js @@ -10,10 +10,10 @@ function offsetToColumnConverter (compilerEvent) { }) } -offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, compilationResult) { +offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, sources) { if (!this.lineBreakPositionsByContent[file]) { - var filename = Object.keys(compilationResult.data.sources)[file] - this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(compilationResult.source.sources[filename].content) + var filename = Object.keys(sources)[file] + this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(sources[filename].content) } return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) } From cda14a10a32aa5c765a25f1f3d100304d58c13f3 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Jul 2018 21:58:02 +0200 Subject: [PATCH 5/8] standard --- src/app/plugin/pluginAPI.js | 2 +- src/app/plugin/pluginManager.js | 2 +- test-browser/plugin/remix.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/plugin/pluginAPI.js b/src/app/plugin/pluginAPI.js index 0036e8b873..ebd9b694e4 100644 --- a/src/app/plugin/pluginAPI.js +++ b/src/app/plugin/pluginAPI.js @@ -59,4 +59,4 @@ module.exports = (fileProviders, compiler, udapp, tabbedMenu) => { } } } -} \ No newline at end of file +} diff --git a/src/app/plugin/pluginManager.js b/src/app/plugin/pluginManager.js index 88c94df0dc..5492581284 100644 --- a/src/app/plugin/pluginManager.js +++ b/src/app/plugin/pluginManager.js @@ -182,4 +182,4 @@ module.exports = class PluginManager { self.plugins[name].content.querySelector('iframe').contentWindow.postMessage(value, self.plugins[name].origin) } } -} \ No newline at end of file +} diff --git a/test-browser/plugin/remix.js b/test-browser/plugin/remix.js index fe16c56cb6..415f678711 100644 --- a/test-browser/plugin/remix.js +++ b/test-browser/plugin/remix.js @@ -78,4 +78,4 @@ window.onload = function () { id: 39 }), '*') }) -} \ No newline at end of file +} From 0644b4625bc0ebde1f3982a7357f840492623d91 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Jul 2018 22:49:47 +0200 Subject: [PATCH 6/8] load oraclize plugin --- src/app/panels/righthand-panel.js | 23 +++++++++++++++++++---- src/app/plugin/pluginManager.js | 5 +++++ src/app/plugin/plugins.js | 8 ++++++++ src/app/tabs/settings-tab.js | 14 ++++++++++---- src/app/tabs/tabbed-menu.js | 11 +++++++++++ 5 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 src/app/plugin/plugins.js diff --git a/src/app/panels/righthand-panel.js b/src/app/panels/righthand-panel.js index 77f389f278..aca26f259b 100644 --- a/src/app/panels/righthand-panel.js +++ b/src/app/panels/righthand-panel.js @@ -16,7 +16,9 @@ const PluginTab = require('../tabs/plugin-tab') const TestTab = require('../tabs/test-tab') const RunTab = require('../tabs/run-tab') const PluginAPI = require('../plugin/pluginAPI') +const plugins = require('../plugin/plugins') +var toolTip = require('../ui/tooltip') const EventManager = remixLib.EventManager const styles = styleguide.chooser() @@ -73,11 +75,24 @@ module.exports = class RighthandPanel { self.loadPlugin(json) }) + self.event.register('plugin-name-loadRequest', name => { + if (plugins[name]) { + self.loadPlugin(plugins[name]) + } else { + toolTip('unknown plugin ' + name) + } + }) + self.loadPlugin = function (json) { - var tab = new PluginTab(json) - var content = tab.render() - self._components.tabbedMenu.addTab(json.title, json.title + ' plugin', content) - self._components.pluginManager.register(json, content) + if (self._components.pluginManager.plugins[json.title]) { + self._components.tabbedMenu.removeTabByTitle(json.title) + self._components.pluginManager.unregister(json) + } else { + var tab = new PluginTab(json) + var content = tab.render() + self._components.tabbedMenu.addTab(json.title, json.title + ' plugin', content) + self._components.pluginManager.register(json, content) + } } self._view.dragbar = yo`
` diff --git a/src/app/plugin/pluginManager.js b/src/app/plugin/pluginManager.js index 5492581284..0ea91f1781 100644 --- a/src/app/plugin/pluginManager.js +++ b/src/app/plugin/pluginManager.js @@ -161,6 +161,11 @@ module.exports = class PluginManager { // } }, false) } + unregister (desc) { + const self = this + delete self.plugins[desc.title] + delete self.origins[desc.url] + } register (desc, content) { const self = this self.plugins[desc.title] = {content, origin: desc.url} diff --git a/src/app/plugin/plugins.js b/src/app/plugin/plugins.js new file mode 100644 index 0000000000..68cdb2e31e --- /dev/null +++ b/src/app/plugin/plugins.js @@ -0,0 +1,8 @@ +'use strict' + +module.exports = { + 'oraclize': { + url: 'https://remix-plugin.oraclize.it', + title: 'Oraclize' + } +} diff --git a/src/app/tabs/settings-tab.js b/src/app/tabs/settings-tab.js index ba2d3b0fd5..6b406f86ed 100644 --- a/src/app/tabs/settings-tab.js +++ b/src/app/tabs/settings-tab.js @@ -26,7 +26,8 @@ module.exports = class SettingsTab { compiler: self._components.registry.get('compiler').api, config: self._components.registry.get('config').api, editorPanel: self._components.registry.get('editorpanel').api, - editor: self._components.registry.get('editor').api + editor: self._components.registry.get('editor').api, + righthandpanel: self._components.registry.get('righthandpanel').api } self._view = { /* eslint-disable */ el: null, @@ -155,8 +156,9 @@ module.exports = class SettingsTab {
${self._view.pluginInput} - +
+ { onLoadPlugin('oraclize') }} type="button" value="Oraclize" class="${css.pluginLoad}"> ` self._view.config.remixd = yo` @@ -197,14 +199,18 @@ module.exports = class SettingsTab { function onchangeOption (event) { self._deps.config.set('settings/always-use-vm', !self._deps.config.get('settings/always-use-vm')) } - function onloadPlugin (event) { + function onLoadPlugin (name) { + // @TODO: BAD! REFACTOR: no module should trigger events of another modules emitter + self._deps.righthandpanel.event.trigger('plugin-name-loadRequest', [name]) + } + function onloadPluginJson (event) { try { var json = JSON.parse(self._view.pluginInput.value) } catch (e) { return modal.alert('cannot parse the plugin definition to JSON') } // @TODO: BAD! REFACTOR: no module should trigger events of another modules emitter - self._events.rhp.trigger('plugin-loadRequest', [json]) + self._deps.righthandpanel.event.trigger('plugin-loadRequest', [json]) } function onswitch2darkTheme (event) { styleGuide.switchTheme('dark') diff --git a/src/app/tabs/tabbed-menu.js b/src/app/tabs/tabbed-menu.js index ca9f39de28..69a1b2aa5b 100644 --- a/src/app/tabs/tabbed-menu.js +++ b/src/app/tabs/tabbed-menu.js @@ -46,6 +46,17 @@ module.exports = class TabbedMenu { if (self._view.el) self._view.el.appendChild(self._view.tabs[title]) if (self._view.viewport) self._view.viewport.appendChild(self._view.contents[title]) } + removeTabByTitle (title) { + const self = this + if (self._view.tabs[title]) { + self._view.tabs[title].parentNode.removeChild(self._view.tabs[title]) + } + if (self._view.contents[title]) { + self._view.contents[title].parentNode.removeChild(self._view.contents[title]) + } + delete self._view.contents[title] + delete self._view.tabs[title] + } getTabByClass (tabClass) { const self = this return self._view.el.querySelector(`li.${tabClass}`) From 640b7a47166c9ef7fc283dd93aa2ad3b37522362 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 4 Jul 2018 15:18:35 +0200 Subject: [PATCH 7/8] remove bad rebasing token --- src/app/panels/terminal.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/app/panels/terminal.js b/src/app/panels/terminal.js index 1c794be37a..25b2c01c74 100644 --- a/src/app/panels/terminal.js +++ b/src/app/panels/terminal.js @@ -579,13 +579,5 @@ function domTerminalFeatures (self, scopedCommands) { } function blockify (el) { return yo`
${el}
` } -<<<<<<< HEAD -======= -// PENDING TX -function updatePendingTxs (udapp, el) { - var count = Object.keys(udapp.pendingTransactions()).length - el.innerText = count -} ->>>>>>> fix terminal api module.exports = Terminal From cd8672ffae12cbdf36cbc48fad44e57d531038ba Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 4 Jul 2018 15:25:35 +0200 Subject: [PATCH 8/8] fix bad reference --- src/app/panels/terminal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/panels/terminal.js b/src/app/panels/terminal.js index 25b2c01c74..5dfc88600b 100644 --- a/src/app/panels/terminal.js +++ b/src/app/panels/terminal.js @@ -74,7 +74,7 @@ class Terminal { self.registerCommand('script', function execute (args, scopedCommands, append) { var script = String(args[0]) scopedCommands.log(`> ${script}`) - if (self._opts.cmdInterpreter && self.opts.cmdInterpreter.interpret(script)) return + if (self._opts.cmdInterpreter && self._opts.cmdInterpreter.interpret(script)) return self._shell(script, scopedCommands, function (error, output) { if (error) scopedCommands.error(error) else scopedCommands.log(output)