Merge branch 'master' into logfix

pull/5370/head
bunsenstraat 4 years ago committed by GitHub
commit 0bc6ec37e8
  1. 7
      .circleci/config.yml
  2. 9
      apps/remix-ide-e2e/src/helpers/init.ts
  3. 2
      apps/remix-ide-e2e/src/tests/ballot.test.ts
  4. 2
      apps/remix-ide-e2e/src/tests/ballot_0_4_11.spec.ts
  5. 4
      apps/remix-ide-e2e/src/tests/debugger.spec.ts
  6. 4
      apps/remix-ide-e2e/src/tests/gist.spec.ts
  7. 2
      apps/remix-ide-e2e/src/tests/url.spec.ts
  8. 20
      apps/remix-ide/src/app/panels/file-panel.js
  9. 5
      apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js
  10. 23
      libs/remix-debug/src/solidity-decoder/astHelper.ts
  11. 8
      libs/remix-debug/src/solidity-decoder/decodeInfo.ts
  12. 2
      libs/remix-simulator/src/methods/transactions.ts
  13. 3
      libs/remix-simulator/src/vm-context.ts
  14. 2
      libs/remix-tests/src/deployer.ts
  15. 13
      libs/remix-tests/src/runTestFiles.ts
  16. 4
      libs/remix-tests/src/testRunner.ts
  17. 138
      libs/remix-ui/file-explorer/src/lib/actions/fileSystem.ts
  18. 2
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx
  19. 19
      libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx
  20. 6
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  21. 2
      package.json

@ -238,8 +238,8 @@ jobs:
steps: steps:
- checkout - checkout
- run: npm install - run: npm install
- run: npx nx build remix-ide --with-deps
- run: npm run downloadsolc_assets - run: npm run downloadsolc_assets
- run: npx nx build remix-ide --with-deps
- run: - run:
name: Deploy name: Deploy
command: | command: |
@ -267,6 +267,7 @@ jobs:
- checkout - checkout
- setup_remote_docker - setup_remote_docker
- run: npm install - run: npm install
- run: npm run downloadsolc_assets
- run: npx nx build remix-ide --with-deps - run: npx nx build remix-ide --with-deps
- run: ./apps/remix-ide/ci/copy_resources.sh - run: ./apps/remix-ide/ci/copy_resources.sh
- run: ./apps/remix-ide/ci/publishIpfs - run: ./apps/remix-ide/ci/publishIpfs
@ -291,8 +292,8 @@ jobs:
steps: steps:
- checkout - checkout
- run: npm install - run: npm install
- run: npx nx build remix-ide --with-deps
- run: npm run downloadsolc_assets - run: npm run downloadsolc_assets
- run: npx nx build remix-ide --with-deps
- run: - run:
name: Deploy name: Deploy
command: | command: |
@ -320,8 +321,8 @@ jobs:
- checkout - checkout
- run: npm install - run: npm install
- run: npm run build:libs - run: npm run build:libs
- run: npm run build
- run: npm run downloadsolc_assets - run: npm run downloadsolc_assets
- run: npm run build
- run: - run:
name: Deploy name: Deploy
command: | command: |

@ -2,18 +2,11 @@ import { NightwatchBrowser } from 'nightwatch'
require('dotenv').config() require('dotenv').config()
export default function (browser: NightwatchBrowser, callback: VoidFunction, url?: string, preloadPlugins = true, closeWorkspaceAlert = true): void { export default function (browser: NightwatchBrowser, callback: VoidFunction, url?: string, preloadPlugins = true): void {
browser browser
.url(url || 'http://127.0.0.1:8080') .url(url || 'http://127.0.0.1:8080')
.pause(5000) .pause(5000)
.switchBrowserTab(0) .switchBrowserTab(0)
.perform((done) => {
if (closeWorkspaceAlert) {
browser.waitForElementVisible('*[data-id="modalDialogModalBody"]', 60000)
.modalFooterOKClick()
}
done()
})
.fullscreenWindow(() => { .fullscreenWindow(() => {
if (preloadPlugins) { if (preloadPlugins) {
initModules(browser, () => { initModules(browser, () => {

@ -49,7 +49,7 @@ module.exports = {
'Debug Ballot / delegate': function (browser: NightwatchBrowser) { 'Debug Ballot / delegate': function (browser: NightwatchBrowser) {
browser.pause(500) browser.pause(500)
.click('*[data-id="txLoggerDebugButton0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3"]') .click('*[data-id="txLoggerDebugButton0xf88bc0ac0761f78d8c883b32550c68dadcdb095595c30e1a1b7c583e5e958dcb"]')
.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.pause(2000) .pause(2000)

@ -45,7 +45,7 @@ module.exports = {
'Debug Ballot / delegate': function (browser: NightwatchBrowser) { 'Debug Ballot / delegate': function (browser: NightwatchBrowser) {
browser.pause(500) browser.pause(500)
.click('*[data-id="txLoggerDebugButton0x41fab8ea5b1d9fba5e0a6545ca1a2d62fff518578802c033c2b9a031a01c31b3"]') .click('*[data-id="txLoggerDebugButton0xf88bc0ac0761f78d8c883b32550c68dadcdb095595c30e1a1b7c583e5e958dcb"]')
.pause(2000) .pause(2000)
.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
.click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]') .click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')

@ -420,7 +420,7 @@ const localVariable_step717_ABIEncoder = { // eslint-disable-line
const jsGetTrace = `(async () => { const jsGetTrace = `(async () => {
try { try {
const result = await remix.call('debugger', 'getTrace', '0xbf309c0d71579d595f04a42e89d66d1ec17523dd3edea710b03f46a9b82ee0af') const result = await remix.call('debugger', 'getTrace', '0xa38bff6f06e7c4fc91df1db6aa31a69ab5d5882faa953b1e7a88bfa523268ed7')
console.log('result ', result) console.log('result ', result)
} catch (e) { } catch (e) {
console.log(e.message) console.log(e.message)
@ -429,7 +429,7 @@ const jsGetTrace = `(async () => {
const jsDebug = `(async () => { const jsDebug = `(async () => {
try { try {
const result = await remix.call('debugger', 'debug', '0xbf309c0d71579d595f04a42e89d66d1ec17523dd3edea710b03f46a9b82ee0af') const result = await remix.call('debugger', 'debug', '0xa38bff6f06e7c4fc91df1db6aa31a69ab5d5882faa953b1e7a88bfa523268ed7')
console.log('result ', result) console.log('result ', result)
} catch (e) { } catch (e) {
console.log(e.message) console.log(e.message)

@ -54,8 +54,8 @@ module.exports = {
.click('[data-id="default_workspace-modal-footer-cancel-react"]') .click('[data-id="default_workspace-modal-footer-cancel-react"]')
.executeScript(`remix.loadgist('${gistid}')`) .executeScript(`remix.loadgist('${gistid}')`)
// .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('gists') } done() }) // .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('gists') } done() })
.waitForElementVisible(`[data-id="treeViewLitreeViewItem/gist-${gistid}"]`) .waitForElementVisible(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)
.click(`[data-id="treeViewLitreeViewItem/gist-${gistid}"]`) .click(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)
.openFile(`gist-${gistid}/README.txt`) .openFile(`gist-${gistid}/README.txt`)
} }
}) })

@ -10,7 +10,7 @@ const sources = [
module.exports = { module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0', true, false) init(browser, done, 'http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0', true)
}, },
'@sources': function () { '@sources': function () {

@ -166,12 +166,26 @@ module.exports = class Filepanel extends ViewPlugin {
return return
} }
// insert example contracts if there are no files to show // insert example contracts if there are no files to show
return new Promise((resolve, reject) => {
this._deps.fileProviders.browser.resolveDirectory('/', async (error, filesList) => { this._deps.fileProviders.browser.resolveDirectory('/', async (error, filesList) => {
if (error) console.error(error) if (error) return reject(error)
if (Object.keys(filesList).length === 0) { if (Object.keys(filesList).length === 0) {
await this.createWorkspace('default_workspace') await this.createWorkspace('default_workspace')
resolve('default_workspace')
} else {
this._deps.fileProviders.browser.resolveDirectory('.workspaces', async (error, filesList) => {
if (error) return reject(error)
if (Object.keys(filesList).length > 0) {
const workspacePath = Object.keys(filesList)[0].split('/').filter(val => val)
const workspaceName = workspacePath[workspacePath.length - 1]
this._deps.fileProviders.workspace.setWorkspace(workspaceName)
return resolve(workspaceName)
}
return reject(new Error('Can\'t find available workspace.'))
})
} }
this.getWorkspaces() })
}) })
} }
@ -213,13 +227,11 @@ module.exports = class Filepanel extends ViewPlugin {
await this.request.setWorkspace(workspaceName) // tells the react component to switch to that workspace await this.request.setWorkspace(workspaceName) // tells the react component to switch to that workspace
if (setDefaults) { if (setDefaults) {
for (const file in examples) { for (const file in examples) {
setTimeout(async () => { // space creation of files to give react ui time to update.
try { try {
await workspaceProvider.set(examples[file].name, examples[file].content) await workspaceProvider.set(examples[file].name, examples[file].content)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} }
}, 10)
} }
} }
} }

@ -170,6 +170,7 @@ class CompilerContainer {
_retrieveVersion (version) { _retrieveVersion (version) {
if (!version) version = this._view.versionSelector.value if (!version) version = this._view.versionSelector.value
if (version === 'builtin') version = this.data.defaultVersion
return semver.coerce(version) ? semver.coerce(version).version : '' return semver.coerce(version) ? semver.coerce(version).version : ''
} }
@ -487,7 +488,7 @@ class CompilerContainer {
this._view.versionSelector.appendChild(option) this._view.versionSelector.appendChild(option)
} }
}) })
if (semver.lt(this._retrieveVersion(), 'v0.4.12+commit.194ff033.js')) { if (this.data.selectedVersion !== 'builtin' && semver.lt(this._retrieveVersion(), 'v0.4.12+commit.194ff033.js')) {
toaster(yo` toaster(yo`
<div> <div>
<b>Old compiler usage detected.</b> <b>Old compiler usage detected.</b>
@ -500,7 +501,7 @@ class CompilerContainer {
// Workers cannot load js on "file:"-URLs and we get a // Workers cannot load js on "file:"-URLs and we get a
// "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium, // "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium,
// resort to non-worker version in that case. // resort to non-worker version in that case.
if (this.data.selectedVersion !== 'builtin' && canUseWorker(this.data.selectedVersion)) { if (canUseWorker(this._retrieveVersion())) {
this.compileTabLogic.compiler.loadVersion(true, url) this.compileTabLogic.compiler.loadVersion(true, url)
this.setVersionText('(loading using worker)') this.setVersionText('(loading using worker)')
} else { } else {

@ -26,6 +26,27 @@ export function extractContractDefinitions (sourcesList) {
return ret return ret
} }
/**
* return nodes from an ast @arg sourcesList that are declared outside of a ContractDefinition @astList
*
* @param {Object} sourcesList - sources list (containing root AST node)
* @return {Object} - returns a list of node
*/
export function extractOrphanDefinitions (sourcesList) {
const ret = []
for (const k in sourcesList) {
const ast = sourcesList[k].ast
if (ast.nodes && ast.nodes.length) {
for (const node of ast.nodes) {
if (node.nodeType !== 'ContractDefinition') {
ret.push(node)
}
}
}
}
return ret
}
/** /**
* returns the linearized base contracts of the contract @arg id * returns the linearized base contracts of the contract @arg id
* *
@ -54,7 +75,7 @@ export function extractStateDefinitions (contractName, sourcesList, contracts) {
if (!node) { if (!node) {
return null return null
} }
const stateItems = [] const stateItems = extractOrphanDefinitions(sourcesList)
const stateVar = [] const stateVar = []
const baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById) const baseContracts = getLinearizedBaseContracts(node.id, contracts.contractsById)
baseContracts.reverse() baseContracts.reverse()

@ -233,11 +233,11 @@ function getEnum (type, stateDefinitions, contractName) {
* @return {Array} containing all members of the current struct type * @return {Array} containing all members of the current struct type
*/ */
function getStructMembers (type, stateDefinitions, contractName, location) { function getStructMembers (type, stateDefinitions, contractName, location) {
const split = type.split('.') if (type.indexOf('.') === -1) {
if (!split.length) {
type = contractName + '.' + type type = contractName + '.' + type
} else { }
contractName = split[0] if (!contractName) {
contractName = type.split('.')[0]
} }
const state = stateDefinitions[contractName] const state = stateDefinitions[contractName]
if (state) { if (state) {

@ -113,7 +113,7 @@ export class Transactions {
} }
eth_estimateGas (payload, cb) { eth_estimateGas (payload, cb) {
cb(null, 3000000) cb(null, 10000000 * 8)
} }
eth_getCode (payload, cb) { eth_getCode (payload, cb) {

@ -122,7 +122,8 @@ export class VMContext {
const vm = new VM({ const vm = new VM({
common, common,
activatePrecompiles: true, activatePrecompiles: true,
stateManager: stateManager stateManager: stateManager,
allowUnlimitedContractSize: true
}) })
const web3vm = new remixLibVm.Web3VMProvider() const web3vm = new remixLibVm.Web3VMProvider()

@ -110,7 +110,7 @@ export function deployAll (compileResult: compilationInterface, web3: Web3, with
const params = '' // we suppose that the test contract does not have any param in the constructor const params = '' // we suppose that the test contract does not have any param in the constructor
execution.txFormat.encodeConstructorCallAndDeployLibraries(contractName, contract.raw, compileResult, params, funAbi, encodeDataFinalCallback, encodeDataStepCallback, encodeDataDeployLibraryCallback) execution.txFormat.encodeConstructorCallAndDeployLibraries(contractName, contract.raw, compileResult, params, funAbi, encodeDataFinalCallback, encodeDataStepCallback, encodeDataDeployLibraryCallback)
}, function (err) { }, function (err) {
if (err) next(err) if (err) return next(err)
next(null, contracts) next(null, contracts)
}) })
} }

@ -63,9 +63,16 @@ export function runTestFiles (filepath: string, isDirectory: boolean, web3: Web3
} }
deployAll(compilationResult, web3, false, (err, contracts) => { deployAll(compilationResult, web3, false, (err, contracts) => {
if (err) { if (err) {
next(err) // If contract deployment fails because of 'Out of Gas' error, try again with double gas
} // This is temporary, should be removed when remix-tests will have a dedicated UI to
next(null, compilationResult, contracts) // accept deployment params from UI
if (err.message.includes('The contract code couldn\'t be stored, please check your gas limit')) {
deployAll(compilationResult, web3, true, (error, contracts) => {
if (error) next([{ message: 'contract deployment failed after trying twice: ' + error.message, severity: 'error' }]) // IDE expects errors in array
else next(null, compilationResult, contracts)
})
} else { next([{ message: 'contract deployment failed: ' + err.message, severity: 'error' }]) } // IDE expects errors in array
} else { next(null, compilationResult, contracts) }
}) })
}, },
function determineTestContractsToRun (compilationResult: compilationInterface, contracts: any, next) { function determineTestContractsToRun (compilationResult: compilationInterface, contracts: any, next) {

@ -238,7 +238,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
sender = opts.accounts[sender] sender = opts.accounts[sender]
} }
} }
let sendParams: Record<string, string> | null = null let sendParams: Record<string, any> | null = null
if (sender) sendParams = { from: sender } if (sender) sendParams = { from: sender }
if (func.inputs && func.inputs.length > 0) { return resultsCallback(new Error(`Method '${func.name}' can not have parameters inside a test contract`), { passingNum, failureNum, timePassed }) } if (func.inputs && func.inputs.length > 0) { return resultsCallback(new Error(`Method '${func.name}' can not have parameters inside a test contract`), { passingNum, failureNum, timePassed }) }
const method = testObject.methods[func.name].apply(testObject.methods[func.name], []) const method = testObject.methods[func.name].apply(testObject.methods[func.name], [])
@ -280,6 +280,8 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
else sendParams = { value } else sendParams = { value }
} }
} }
if (!sendParams) sendParams = {}
sendParams.gas = 10000000 * 8
method.send(sendParams).on('receipt', (receipt) => { method.send(sendParams).on('receipt', (receipt) => {
try { try {
const time: number = (Date.now() - startTime) / 1000.0 const time: number = (Date.now() - startTime) / 1000.0

@ -2,6 +2,12 @@ import React from 'react'
import { File } from '../types' import { File } from '../types'
import { extractNameFromKey, extractParentFromKey } from '../utils' import { extractNameFromKey, extractParentFromKey } from '../utils'
const queuedEvents = []
const pendingEvents = {}
let provider = null
let plugin = null
let dispatch: React.Dispatch<any> = null
export const fetchDirectoryError = (error: any) => { export const fetchDirectoryError = (error: any) => {
return { return {
type: 'FETCH_DIRECTORY_ERROR', type: 'FETCH_DIRECTORY_ERROR',
@ -183,35 +189,25 @@ export const fileRenamedSuccess = (path: string, removePath: string, files) => {
} }
} }
export const init = (provider, workspaceName: string, plugin, registry) => (dispatch: React.Dispatch<any>) => { export const init = (fileProvider, filePanel, registry) => (reducerDispatch: React.Dispatch<any>) => {
provider = fileProvider
plugin = filePanel
dispatch = reducerDispatch
if (provider) { if (provider) {
provider.event.on('fileAdded', async (filePath) => { provider.event.on('fileAdded', async (filePath) => {
if (extractParentFromKey(filePath) === '/.workspaces') return await executeEvent('fileAdded', filePath)
const path = extractParentFromKey(filePath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
dispatch(fileAddedSuccess(path, data))
if (filePath.includes('_test.sol')) {
plugin.emit('newTestFileCreated', filePath)
}
}) })
provider.event.on('folderAdded', async (folderPath) => { provider.event.on('folderAdded', async (folderPath) => {
if (extractParentFromKey(folderPath) === '/.workspaces') return await executeEvent('folderAdded', folderPath)
const path = extractParentFromKey(folderPath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
dispatch(folderAddedSuccess(path, data))
}) })
provider.event.on('fileRemoved', async (removePath) => { provider.event.on('fileRemoved', async (removePath) => {
const path = extractParentFromKey(removePath) || provider.workspace || provider.type || '' await executeEvent('fileRemoved', removePath)
dispatch(fileRemovedSuccess(path, removePath))
}) })
provider.event.on('fileRenamed', async (oldPath) => { provider.event.on('fileRenamed', async (oldPath) => {
const path = extractParentFromKey(oldPath) || provider.workspace || provider.type || '' await executeEvent('fileRenamed', oldPath)
const data = await fetchDirectoryContent(provider, path) })
provider.event.on('rootFolderChanged', async () => {
dispatch(fileRenamedSuccess(path, oldPath, data)) await executeEvent('rootFolderChanged')
}) })
provider.event.on('fileExternallyChanged', async (path: string, file: { content: string }) => { provider.event.on('fileExternallyChanged', async (path: string, file: { content: string }) => {
const config = registry.get('config').api const config = registry.get('config').api
@ -232,10 +228,6 @@ export const init = (provider, workspaceName: string, plugin, registry) => (disp
provider.event.on('fileRenamedError', async () => { provider.event.on('fileRenamedError', async () => {
dispatch(displayNotification('File Renamed Failed', '', 'Ok', 'Cancel')) dispatch(displayNotification('File Renamed Failed', '', 'Ok', 'Cancel'))
}) })
provider.event.on('rootFolderChanged', async () => {
workspaceName = provider.workspace || provider.type || ''
fetchDirectory(provider, workspaceName)(dispatch)
})
dispatch(fetchProviderSuccess(provider)) dispatch(fetchProviderSuccess(provider))
} else { } else {
dispatch(fetchProviderError('No provider available')) dispatch(fetchProviderError('No provider available'))
@ -294,3 +286,99 @@ export const hideNotification = () => {
export const closeNotificationModal = () => (dispatch: React.Dispatch<any>) => { export const closeNotificationModal = () => (dispatch: React.Dispatch<any>) => {
dispatch(hideNotification()) dispatch(hideNotification())
} }
const fileAdded = async (filePath: string) => {
if (extractParentFromKey(filePath) === '/.workspaces') return
const path = extractParentFromKey(filePath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
await dispatch(fileAddedSuccess(path, data))
if (filePath.includes('_test.sol')) {
plugin.emit('newTestFileCreated', filePath)
}
}
const folderAdded = async (folderPath: string) => {
if (extractParentFromKey(folderPath) === '/.workspaces') return
const path = extractParentFromKey(folderPath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
await dispatch(folderAddedSuccess(path, data))
}
const fileRemoved = async (removePath: string) => {
const path = extractParentFromKey(removePath) || provider.workspace || provider.type || ''
await dispatch(fileRemovedSuccess(path, removePath))
}
const fileRenamed = async (oldPath: string) => {
const path = extractParentFromKey(oldPath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
await dispatch(fileRenamedSuccess(path, oldPath, data))
}
const rootFolderChanged = async () => {
const workspaceName = provider.workspace || provider.type || ''
await fetchDirectory(provider, workspaceName)(dispatch)
}
const executeEvent = async (eventName: 'fileAdded' | 'folderAdded' | 'fileRemoved' | 'fileRenamed' | 'rootFolderChanged', path?: string) => {
if (Object.keys(pendingEvents).length) {
return queuedEvents.push({ eventName, path })
}
pendingEvents[eventName + path] = { eventName, path }
switch (eventName) {
case 'fileAdded':
await fileAdded(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'folderAdded':
await folderAdded(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'fileRemoved':
await fileRemoved(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'fileRenamed':
await fileRenamed(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'rootFolderChanged':
await rootFolderChanged()
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
}
}

@ -126,7 +126,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
const editRef = useRef(null) const editRef = useRef(null)
useEffect(() => { useEffect(() => {
init(props.filesProvider, props.name, props.plugin, props.registry)(dispatch) init(props.filesProvider, props.plugin, props.registry)(dispatch)
}, []) }, [])
useEffect(() => { useEffect(() => {

@ -66,13 +66,16 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
}, []) }, [])
useEffect(() => { useEffect(() => {
setWarningState([])
if (autoRun) { if (autoRun) {
if (state.data !== null) { if (state.data !== null) {
run(state.data, state.source, state.file) run(state.data, state.source, state.file)
} }
} else {
props.event.trigger('staticAnaysisWarning', [])
} }
return () => { } return () => { }
}, [autoRun, categoryIndex, state]) }, [state])
const message = (name, warning, more, fileName, locationString) : string => { const message = (name, warning, more, fileName, locationString) : string => {
return (` return (`
@ -302,7 +305,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
label="Autorun" label="Autorun"
onChange={() => {}} onChange={() => {}}
/> />
<Button buttonText="Run" onClick={() => run(state.data, state.source, state.file)} disabled={state.data === null}/> <Button buttonText="Run" onClick={() => run(state.data, state.source, state.file)} disabled={state.data === null || categoryIndex.length === 0 }/>
</div> </div>
</div> </div>
<div id="staticanalysismodules" className="list-group list-group-flush"> <div id="staticanalysismodules" className="list-group list-group-flush">
@ -323,22 +326,22 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => {
{state.file} {state.file}
</span> </span>
</div> </div>
{ categoryIndex.length > 0 && Object.entries(warningState).length > 0 && {Object.entries(warningState).length > 0 &&
<div id='staticanalysisresult' > <div id='staticanalysisresult' >
<div className="mb-4"> <div className="mb-4">
{ {
(Object.entries(warningState).map((element) => ( (Object.entries(warningState).map((element, index) => (
<> <div key={index}>
<span className="text-dark h6">{element[0]}</span> <span className="text-dark h6">{element[0]}</span>
{element[1].map(x => ( {element[1].map((x, i) => (
x.hasWarning ? ( x.hasWarning ? (
<div id={`staticAnalysisModule${element[1].warningModuleName}`}> <div id={`staticAnalysisModule${element[1].warningModuleName}`} key={i}>
<ErrorRenderer message={x.msg} opt={x.options} warningErrors={ x.warningErrors} editor={props.analysisModule}/> <ErrorRenderer message={x.msg} opt={x.options} warningErrors={ x.warningErrors} editor={props.analysisModule}/>
</div> </div>
) : null ) : null
))} ))}
</> </div>
))) )))
} }
</div> </div>

@ -71,7 +71,7 @@ export const Workspace = (props: WorkspaceProps) => {
} }
useEffect(() => { useEffect(() => {
const getWorkspaces = async () => { let getWorkspaces = async () => {
if (props.workspaces && Array.isArray(props.workspaces)) { if (props.workspaces && Array.isArray(props.workspaces)) {
if (props.workspaces.length > 0 && state.currentWorkspace === NO_WORKSPACE) { if (props.workspaces.length > 0 && state.currentWorkspace === NO_WORKSPACE) {
props.workspace.setWorkspace(props.workspaces[0]) props.workspace.setWorkspace(props.workspaces[0])
@ -87,6 +87,10 @@ export const Workspace = (props: WorkspaceProps) => {
} }
getWorkspaces() getWorkspaces()
return () => {
getWorkspaces = async () => {}
}
}, [props.workspaces]) }, [props.workspaces])
const localhostDisconnect = () => { const localhostDisconnect = () => {

@ -50,7 +50,7 @@
"bumpVersion:libs": "gulp & gulp syncLibVersions;", "bumpVersion:libs": "gulp & gulp syncLibVersions;",
"browsertest": "sleep 5 && npm run nightwatch_local", "browsertest": "sleep 5 && npm run nightwatch_local",
"csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='apps/remix-ide/src/assets/css/font-awesome.min.css' apps/remix-ide/src/assets/css/", "csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='apps/remix-ide/src/assets/css/font-awesome.min.css' apps/remix-ide/src/assets/css/",
"downloadsolc_assets": "wget --no-check-certificate https://binaries.soliditylang.org/bin/soljson-v0.8.4+commit.c7e474f2.js -O ./apps/remix-ide/src/assets/js/soljson.js", "downloadsolc_assets": "wget --no-check-certificate https://binaries.soliditylang.org/wasm/soljson-v0.8.4+commit.c7e474f2.js -O ./apps/remix-ide/src/assets/js/soljson.js",
"make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js", "make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js",
"minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false", "minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false",
"nightwatch_parallel": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js --env=chrome,firefox", "nightwatch_parallel": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js --env=chrome,firefox",

Loading…
Cancel
Save