Merge pull request #2828 from ethereum/wasmBuilds

Load wasm builds if available
pull/262/head
yann300 4 years ago committed by GitHub
commit 9e506e99dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      package.json
  2. 4
      src/app/compiler/compiler-helpers.js
  3. 4
      src/app/compiler/compiler-sourceVerifier-fetchAndCompile.js
  4. 54
      src/app/compiler/compiler-utils.js
  5. 13
      src/app/editor/example-contracts.js
  6. 5
      src/app/files/fileProvider.js
  7. 3
      src/app/tabs/compile-tab.js
  8. 63
      src/app/tabs/compileTab/compilerContainer.js
  9. 6
      src/app/tabs/test-tab.js
  10. 1
      src/lib/helper.js
  11. 28
      test-browser/commands/noWorkerErrorFor.js
  12. 7
      test-browser/tests/runAndDeploy.js
  13. 2
      test-browser/tests/solidityUnittests.test.js
  14. 37
      test-browser/tests/usingWebWorker.test.js

@ -165,6 +165,7 @@
"nightwatch_local_firefox": "nightwatch --config nightwatch.js --env firefox",
"nightwatch_local_chrome": "nightwatch --config nightwatch.js --env chrome",
"nightwatch_local_ballot": "nightwatch ./test-browser/tests/ballot.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_usingWorker": "nightwatch ./test-browser/tests/usingWebWorker.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_libraryDeployment": "nightwatch ./test-browser/tests/libraryDeployment.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_solidityImport": "nightwatch ./test-browser/tests/solidityImport.test.js --config nightwatch.js --env chrome ",
"nightwatch_local_recorder": "nightwatch ./test-browser/tests/recorder.test.js --config nightwatch.js --env chrome ",

@ -1,5 +1,5 @@
'use strict'
import { canUseWorker } from './compiler-utils'
import { canUseWorker, urlFromVersion } from './compiler-utils'
import { Compiler } from 'remix-solidity'
import CompilerAbstract from './compiler-abstract'
@ -9,7 +9,7 @@ export const compile = async (compilationTargets, settings) => {
const compiler = new Compiler(() => {})
compiler.set('evmVersion', settings.evmVersion)
compiler.set('optimize', settings.optimize)
compiler.loadVersion(canUseWorker(settings.version), settings.compilerUrl)
compiler.loadVersion(canUseWorker(settings.version), urlFromVersion(settings.version))
compiler.event.register('compilationFinished', (success, compilationData, source) => {
if (!success) return reject(compilationData)
resolve(new CompilerAbstract(settings.version, compilationData, source))

@ -1,7 +1,6 @@
const ethutil = require('ethereumjs-util')
import * as packageJson from '../../../package.json'
import { Plugin } from '@remixproject/engine'
import { urlFromVersion } from './compiler-utils'
import { compile } from './compiler-helpers'
import globalRegistry from '../../global/registry'
@ -108,8 +107,7 @@ export default class FetchAndCompile extends Plugin {
version: data.metadata.compiler.version,
languageName: data.metadata.language,
evmVersion: data.metadata.settings.evmVersion,
optimize: data.metadata.settings.optimizer.enabled,
compilerUrl: urlFromVersion(data.metadata.compiler.version)
optimize: data.metadata.settings.optimizer.enabled
}
try {
setTimeout(_ => this.emit('compiling', settings), 0)

@ -1,48 +1,44 @@
const semver = require('semver')
const minixhr = require('minixhr')
/* global Worker */
export const baseUrl = 'https://solc-bin.ethereum.org/bin'
export const baseURLBin = 'https://solc-bin.ethereum.org/bin'
export const baseURLWasm = 'https://solc-bin.ethereum.org/wasm'
export const pathToURL = {}
/**
* Retrieves the URL of the given compiler version
* @param version is the version of compiler with or without 'soljson-v' prefix and .js postfix
*/
export function urlFromVersion (version) {
return `${baseUrl}/soljson-v${version}.js`
if (!version.startsWith('soljson-v')) version = 'soljson-v' + version
if (!version.endsWith('.js')) version = version + '.js'
return `${pathToURL[version]}/${version}`
}
/**
* Checks if the worker can be used to load a compiler.
* checks a compiler whitelist, browser support and OS.
*/
export function canUseWorker (selectedVersion) {
// Following restrictions should be deleted when Solidity will release fixed versions of compilers.
// See https://github.com/ethereum/remix-ide/issues/2461
const isChrome = !!window.chrome
const os = retrieveOS()
// define a whitelist for Linux
const linuxWL = ['0.4.26', '0.5.3', '0.5.4', '0.5.5']
const version = semver.coerce(selectedVersion)
// defining whitelist for chrome
let isFromWhiteList = false
switch (os) {
case 'Windows':
isFromWhiteList = semver.gt(version, '0.5.2') || version === '0.4.26'
break
case 'Linux':
isFromWhiteList = semver.gt(version, '0.5.13') || linuxWL.includes(version)
break
default :
isFromWhiteList = true
}
return browserSupportWorker() && (!isChrome || (isChrome && isFromWhiteList))
const isNightly = selectedVersion.includes('nightly')
return browserSupportWorker() && (
semver.gt(version, '0.6.3') ||
semver.gt(version, '0.3.6') && !isNightly
)
}
function browserSupportWorker () {
return document.location.protocol !== 'file:' && Worker !== undefined
}
function retrieveOS () {
let osName = 'Unknown OS'
if (navigator.platform.indexOf('Win') !== -1) {
osName = 'Windows'
} else if (navigator.platform.indexOf('Linux') !== -1) {
osName = 'Linux'
}
return osName
// returns a promise for minixhr
export function promisedMiniXhr (url) {
return new Promise((resolve, reject) => {
minixhr(url, (json, event) => {
resolve({ json, event })
})
})
}

@ -1,5 +1,15 @@
'use strict'
const basic = `pragma solidity >=0.2.0 <0.7.0;
/**
* @title Basic contract
*/
contract Basic {
uint someVar;
constructor() public {}
}`
const storage = `pragma solidity >=0.4.22 <0.7.0;
/**
@ -245,5 +255,6 @@ module.exports = {
storage: { name: '1_Storage.sol', content: storage },
owner: { name: '2_Owner.sol', content: owner },
ballot: { name: '3_Ballot.sol', content: ballot },
ballot_test: { name: '4_Ballot_test.sol', content: ballotTest }
ballot_test: { name: '4_Ballot_test.sol', content: ballotTest },
basic: { name: 'basic.sol', content: basic }
}

@ -93,7 +93,10 @@ class FileProvider {
cb = cb || function () {}
var unprefixedpath = this.removePrefix(path)
var exists = window.remixFileSystem.existsSync(unprefixedpath)
if (exists && window.remixFileSystem.readFileSync(unprefixedpath, 'utf8') === content) return true
if (exists && window.remixFileSystem.readFileSync(unprefixedpath, 'utf8') === content) {
cb()
return true
}
if (!exists && unprefixedpath.indexOf('/') !== -1) {
this.createDir(path)
}

@ -116,6 +116,7 @@ class CompileTab extends ViewPlugin {
this.fileManager.events.on('noFileSelected', this.data.eventHandlers.onNoFileSelected)
this.data.eventHandlers.onCompilationFinished = (success, data, source) => {
this._view.errorContainer.appendChild(yo`<span data-id="compilationFinishedWith_${this.getCurrentVersion()}"></span>`)
if (success) {
// forwarding the event to the appManager infra
this.emit('compilationFinished', source.target, source, 'soljson', data)
@ -411,7 +412,7 @@ class CompileTab extends ViewPlugin {
render () {
if (this._view.el) return this._view.el
this.onActivationInternal()
this._view.errorContainer = yo`<div class="${css.errorBlobs} p-4"></div>`
this._view.errorContainer = yo`<div class="${css.errorBlobs} p-4" data-id="compiledErrors" ></div>`
this._view.contractSelection = this.contractSelection()
this._view.compilerContainer = this.compilerContainer.render()
this.compilerContainer.activate()

@ -1,12 +1,11 @@
const yo = require('yo-yo')
const minixhr = require('minixhr')
const helper = require('../../../lib/helper')
const addTooltip = require('../../ui/tooltip')
const semver = require('semver')
const modalDialogCustom = require('../../ui/modal-dialog-custom')
const css = require('../styles/compile-tab-styles')
import { canUseWorker } from '../../compiler/compiler-utils'
import { canUseWorker, baseURLBin, baseURLWasm, urlFromVersion, pathToURL, promisedMiniXhr } from '../../compiler/compiler-utils'
class CompilerContainer {
@ -24,8 +23,7 @@ class CompilerContainer {
timeout: 300,
allversions: null,
selectedVersion: null,
defaultVersion: 'soljson-v0.6.6+commit.6c089d02.js', // this default version is defined: in makeMockCompiler (for browser test) and in package.json (downloadsolc_root) for the builtin compiler
baseurl: 'https://solc-bin.ethereum.org/bin'
defaultVersion: 'soljson-v0.6.6+commit.6c089d02.js' // this default version is defined: in makeMockCompiler (for browser test) and in package.json (downloadsolc_root) for the builtin compiler
}
}
@ -383,13 +381,13 @@ class CompilerContainer {
if (this.data.selectedVersion.indexOf('soljson') !== 0 || helper.checkSpecialChars(this.data.selectedVersion)) {
return console.log('loading ' + this.data.selectedVersion + ' not allowed')
}
url = `${this.data.baseurl}/${this.data.selectedVersion}`
url = `${urlFromVersion(this.data.selectedVersion)}`
}
// Workers cannot load js on "file:"-URLs and we get a
// "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium,
// resort to non-worker version in that case.
if (canUseWorker(this.data.selectedVersion)) {
if (this.data.selectedVersion !== 'builtin' && canUseWorker(this.data.selectedVersion)) {
this.compileTabLogic.compiler.loadVersion(true, url)
this.setVersionText('(loading using worker)')
} else {
@ -413,27 +411,42 @@ class CompilerContainer {
if (this._view.version) this._view.version.innerText = text
}
fetchAllVersion (callback) {
minixhr(`${this.data.baseurl}/list.json`, (json, event) => {
// @TODO: optimise and cache results to improve app loading times #2461
var allversions, selectedVersion
if (event.type !== 'error') {
try {
const data = JSON.parse(json)
allversions = data.builds.slice().reverse()
selectedVersion = this.data.defaultVersion
if (this.queryParams.get().version) selectedVersion = this.queryParams.get().version
} catch (e) {
addTooltip('Cannot load compiler version list. It might have been blocked by an advertisement blocker. Please try deactivating any of them from this page and reload.')
}
} else {
allversions = [{ path: 'builtin', longVersion: 'latest local version' }]
selectedVersion = 'builtin'
// fetching both normal and wasm builds and creating a [version, baseUrl] map
async fetchAllVersion (callback) {
let allVersions, selectedVersion, allVersionsWasm
// fetch normal builds
const binRes = await promisedMiniXhr(`${baseURLBin}/list.json`)
// fetch wasm builds
const wasmRes = await promisedMiniXhr(`${baseURLWasm}/list.json`)
if (binRes.event.type === 'error' && wasmRes.event.type === 'error') {
allVersions = [{ path: 'builtin', longVersion: 'latest local version' }]
selectedVersion = 'builtin'
callback(allVersions, selectedVersion)
}
try {
allVersions = JSON.parse(binRes.json).builds.slice().reverse()
selectedVersion = this.data.defaultVersion
if (this.queryParams.get().version) selectedVersion = this.queryParams.get().version
if (wasmRes.event.type !== 'error') {
allVersionsWasm = JSON.parse(wasmRes.json).builds.slice().reverse()
}
callback(allversions, selectedVersion)
})
} catch (e) {
addTooltip('Cannot load compiler version list. It might have been blocked by an advertisement blocker. Please try deactivating any of them from this page and reload. Error: ' + e)
}
// replace in allVersions those compiler builds which exist in allVersionsWasm with new once
if (allVersionsWasm && allVersions) {
allVersions.forEach((compiler, index) => {
const wasmIndex = allVersionsWasm.findIndex(wasmCompiler => { return wasmCompiler.longVersion === compiler.longVersion })
if (wasmIndex !== -1) {
allVersions[index] = allVersionsWasm[wasmIndex]
pathToURL[compiler.path] = baseURLWasm
} else {
pathToURL[compiler.path] = baseURLBin
}
})
}
callback(allVersions, selectedVersion)
}
scheduleCompilation () {
if (!this.config.get('autoCompile')) return
if (this.data.compileTimeout) window.clearTimeout(this.data.compileTimeout)

@ -4,7 +4,7 @@ var tooltip = require('../ui/tooltip')
var css = require('./styles/test-tab-styles')
var remixTests = require('remix-tests')
import { ViewPlugin } from '@remixproject/engine'
import { canUseWorker, baseUrl } from '../compiler/compiler-utils'
import { canUseWorker, urlFromVersion } from '../compiler/compiler-utils'
const TestTabLogic = require('./testTab/testTab')
@ -301,7 +301,7 @@ module.exports = class TestTab extends ViewPlugin {
let runningTest = {}
runningTest[path] = { content }
const {currentVersion, evmVersion, optimize} = this.compileTab.getCurrentCompilerConfig()
const currentCompilerUrl = baseUrl + '/' + currentVersion
const currentCompilerUrl = urlFromVersion(currentVersion)
const compilerConfig = {
currentCompilerUrl,
evmVersion,
@ -327,7 +327,7 @@ module.exports = class TestTab extends ViewPlugin {
const runningTest = {}
runningTest[testFilePath] = { content }
const {currentVersion, evmVersion, optimize} = this.compileTab.getCurrentCompilerConfig()
const currentCompilerUrl = baseUrl + '/' + currentVersion
const currentCompilerUrl = urlFromVersion(currentVersion)
const compilerConfig = {
currentCompilerUrl,
evmVersion,

@ -84,4 +84,3 @@ function find (args, query) {
})
return isMatch
}

@ -0,0 +1,28 @@
const EventEmitter = require('events')
class NoWorkerErrorFor extends EventEmitter {
command (version) {
this.api.perform((done) => {
noWorkerErrorFor(this.api, version, () => {
done()
this.emit('complete')
})
})
return this
}
}
function noWorkerErrorFor (browser, version, callback) {
browser
.setSolidityCompilerVersion(version)
.click('*[data-id="compilerContainerCompileBtn"]')
.waitForElementPresent('*[data-id="compilationFinishedWith_' + version + '"]', 10000)
.notContainsText('*[data-id="compiledErrors"]', 'worker error:undefined')
.notContainsText('*[data-id="compiledErrors"]', 'Uncaught RangeError: Maximum call stack size exceeded')
.notContainsText('*[data-id="compiledErrors"]', 'RangeError: Maximum call stack size exceeded')
.perform(() => {
callback()
})
}
module.exports = NoWorkerErrorFor

@ -31,8 +31,7 @@ module.exports = {
.assert.elementNotPresent('*[data-id="settingsRemixRunSignMsgHash"]')
.assert.elementNotPresent('*[data-id="settingsRemixRunSignMsgSignature"]')
.modalFooterOKClick()
.pause(2000)
.waitForElementPresent('*[data-id="modalDialogContainer"]')
.waitForElementPresent('*[data-id="modalDialogContainer"]', 12000)
.assert.elementPresent('*[data-id="settingsRemixRunSignMsgHash"]')
.assert.elementPresent('*[data-id="settingsRemixRunSignMsgSignature"]')
.modalFooterOKClick()
@ -145,8 +144,8 @@ module.exports = {
.clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="Deploy - transact (not payable)"]')
.click('*[data-id="Deploy - transact (not payable)"]')
.pause(2000)
.waitForElementPresent('*[data-id="modalDialogContainer"]')
.waitForElementPresent('*[data-id="modalDialogContainer"]', 15000)
.pause(10000)
.assert.containsText('*[data-id="modalDialogModalBody"]', 'You are creating a transaction on the main network. Click confirm if you are sure to continue.')
.modalFooterCancelClick()
},

@ -86,7 +86,7 @@ module.exports = {
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.pause(5000)
.click('*[data-id="testTabRunTestsTabStopAction"]')
.pause(2000)
.pause(1000)
.assert.containsText('*[data-id="testTabRunTestsTabStopAction"]', 'Stopping')
.waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 40000)
.assert.containsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'browser/ks2b_test.sol')

@ -0,0 +1,37 @@
'use strict'
var examples = require('../../src/app/editor/example-contracts')
var init = require('../helpers/init')
var sauce = require('./sauce')
var sources = [
{'browser/basic.sol': {content: examples.basic.content}}
]
module.exports = {
before: function (browser, done) {
init(browser, done)
},
'@sources': function () {
return sources
},
'Using Web Worker': function (browser) {
browser
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
.clickLaunchIcon('fileExplorers')
.openFile('browser/basic.sol')
.clickLaunchIcon('solidity')
.execute(() => {
document.getElementById('nightlies').checked = true
})
.noWorkerErrorFor('soljson-v0.3.4+commit.7dab890.js')
.noWorkerErrorFor('soljson-v0.6.5+commit.f956cc89.js')
.noWorkerErrorFor('soljson-v0.6.8-nightly.2020.5.14+commit.a6d0067b.js')
.noWorkerErrorFor('soljson-v0.6.0-nightly.2019.12.17+commit.d13438ee.js')
.noWorkerErrorFor('soljson-v0.4.26+commit.4563c3fc.js')
.execute(() => {
document.getElementById('nightlies').checked = false
})
},
tearDown: sauce
}
Loading…
Cancel
Save