diff --git a/apps/remix-ide/src/app/files/file-explorer.js b/apps/remix-ide/src/app/files/file-explorer.js
deleted file mode 100644
index cef877b68b..0000000000
--- a/apps/remix-ide/src/app/files/file-explorer.js
+++ /dev/null
@@ -1,702 +0,0 @@
-/* global FileReader */
-/* global fetch */
-const async = require('async')
-const Gists = require('gists')
-const modalDialogCustom = require('../ui/modal-dialog-custom')
-const tooltip = require('../ui/tooltip')
-const QueryParams = require('../../lib/query-params')
-const helper = require('../../lib/helper')
-const yo = require('yo-yo')
-const Treeview = require('../ui/TreeView')
-const modalDialog = require('../ui/modaldialog')
-const EventManager = require('events')
-const contextMenu = require('../ui/contextMenu')
-const css = require('./styles/file-explorer-styles')
-const globalRegistry = require('../../global/registry')
-const queryParams = new QueryParams()
-let MENU_HANDLE
-
-function fileExplorer (localRegistry, files, menuItems, plugin) {
- var self = this
- this.events = new EventManager()
- // file provider backend
- this.files = files
- // element currently focused on
- this.focusElement = null
- // path currently focused on
- this.focusPath = null
- const allItems =
- [
- {
- action: 'createNewFile',
- title: 'Create New File',
- icon: 'fas fa-plus-circle'
- },
- {
- action: 'publishToGist',
- title: 'Publish all [browser] explorer files to a github gist',
- icon: 'fab fa-github'
- },
- {
- action: 'uploadFile',
- title: 'Add Local file to the Browser Storage Explorer',
- icon: 'far fa-folder-open'
- },
- {
- action: 'updateGist',
- title: 'Update the current [gist] explorer',
- icon: 'fab fa-github'
- }
- ]
- // menu items
- this.menuItems = allItems.filter(
- (item) => {
- if (menuItems) return menuItems.find((name) => { return name === item.action })
- }
- )
-
- self._components = {}
- self._components.registry = localRegistry || globalRegistry
- self._deps = {
- config: self._components.registry.get('config').api,
- editor: self._components.registry.get('editor').api,
- fileManager: self._components.registry.get('filemanager').api
- }
-
- self.events.register('focus', function (path) {
- self._deps.fileManager.open(path)
- })
-
- self._components.registry.put({ api: self, name: `fileexplorer/${self.files.type}` })
-
- // warn if file changed outside of Remix
- function remixdDialog () {
- return yo`
This file has been changed outside of Remix IDE.
`
- }
-
- this.files.event.register('fileExternallyChanged', (path, file) => {
- if (self._deps.config.get('currentFile') === path && self._deps.editor.currentContent() && self._deps.editor.currentContent() !== file.content) {
- if (this.files.isReadOnly(path)) return self._deps.editor.setText(file.content)
-
- modalDialog(path + ' changed', remixdDialog(),
- {
- label: 'Replace by the new content',
- fn: () => {
- self._deps.editor.setText(file.content)
- }
- },
- {
- label: 'Keep the content displayed in Remix',
- fn: () => {}
- }
- )
- }
- })
-
- // register to event of the file provider
- files.event.on('fileRemoved', fileRemoved)
- files.event.on('fileRenamed', fileRenamed)
- files.event.on('fileRenamedError', fileRenamedError)
- files.event.on('fileAdded', fileAdded)
- files.event.on('folderAdded', folderAdded)
-
- function fileRenamedError (error) {
- modalDialogCustom.alert(error)
- }
-
- function fileAdded (filepath) {
- self.ensureRoot(() => {
- const folderpath = filepath.split('/').slice(0, -1).join('/')
- const currentTree = self.treeView.nodeAt(folderpath)
- if (!self.treeView.isExpanded(folderpath)) self.treeView.expand(folderpath)
- if (currentTree) {
- self.files.resolveDirectory(folderpath, (error, fileTree) => {
- if (error) console.error(error)
- if (!fileTree) return
- fileTree = normalize(folderpath, fileTree)
- self.treeView.updateNodeFromJSON(folderpath, fileTree, true)
- self.focusElement = self.treeView.labelAt(self.focusPath)
- // TODO: here we update the selected file (it applicable)
- // cause we are refreshing the interface of the whole directory when there's a new file.
- if (self.focusElement && !self.focusElement.classList.contains('bg-secondary')) {
- self.focusElement.classList.add('bg-secondary')
- }
- })
- }
- })
- }
-
- function extractNameFromKey (key) {
- const keyPath = key.split('/')
-
- return keyPath[keyPath.length - 1]
- }
-
- function folderAdded (folderpath) {
- self.ensureRoot(() => {
- folderpath = folderpath.split('/').slice(0, -1).join('/')
- self.files.resolveDirectory(folderpath, (error, fileTree) => {
- if (error) console.error(error)
- if (!fileTree) return
- fileTree = normalize(folderpath, fileTree)
- self.treeView.updateNodeFromJSON(folderpath, fileTree, true)
- if (!self.treeView.isExpanded(folderpath)) self.treeView.expand(folderpath)
- })
- })
- }
-
- function fileRemoved (filepath) {
- const label = self.treeView.labelAt(filepath)
- filepath = filepath.split('/').slice(0, -1).join('/')
-
- if (label && label.parentElement) {
- label.parentElement.removeChild(label)
- }
-
- self.updatePath(filepath)
- }
-
- function fileRenamed (oldName, newName, isFolder) {
- fileRemoved(oldName)
- fileAdded(newName)
- }
-
- // make interface and register to nodeClick, leafClick
- self.treeView = new Treeview({
- extractData: function extractData (value, tree, key) {
- var newValue = {}
- // var isReadOnly = false
- var isFile = false
- Object.keys(value).filter(function keep (x) {
- if (x === '/content') isFile = true
- if (x[0] !== '/') return true
- }).forEach(function (x) { newValue[x] = value[x] })
- return {
- path: (tree || {}).path ? tree.path + '/' + key : key,
- children: isFile ? undefined
- : value instanceof Array ? value.map((item, index) => ({
- key: index, value: item
- })) : value instanceof Object ? Object.keys(value).map(subkey => ({
- key: subkey, value: value[subkey]
- })) : undefined
- }
- },
- formatSelf: function formatSelf (key, data, li) {
- const isRoot = data.path === self.files.type
- const isFolder = !!data.children
- return yo`
-
-
- ${key.split('/').pop()}
-
- ${isRoot ? self.renderMenuItems() : ''}
-
- `
- }
- })
-
- /**
- * Extracts first two folders as a subpath from the path.
- **/
- function extractExternalFolder (path) {
- const firstSlIndex = path.indexOf('/', 1)
- if (firstSlIndex === -1) return ''
- const secondSlIndex = path.indexOf('/', firstSlIndex + 1)
- if (secondSlIndex === -1) return ''
- return path.substring(0, secondSlIndex)
- }
-
- self.treeView.event.register('nodeRightClick', function (key, data, label, event) {
- if (self.files.readonly) return
- if (key === self.files.type) return
- MENU_HANDLE && MENU_HANDLE.hide(null, true)
- const actions = {}
- const provider = self._deps.fileManager.fileProviderOf(key)
- actions['Create File'] = () => self.createNewFile(key)
- actions['Create Folder'] = () => self.createNewFolder(key)
- // @todo(#2386) not fully implemented. Readd later when fixed
- if (provider.isExternalFolder(key)) {
- /* actions['Discard changes'] = () => {
- modalDialogCustom.confirm(
- 'Discard changes',
- 'Are you sure you want to discard all your changes?',
- () => { self.files.discardChanges(key) },
- () => {}
- )
- } */
- } else {
- const folderPath = extractExternalFolder(key)
- actions.Rename = () => {
- if (self.files.isReadOnly(key)) { return tooltip('cannot rename folder. ' + self.files.type + ' is a read only explorer') }
- var name = label.querySelector('span[data-path="' + key + '"]')
- if (name) editModeOn(name)
- }
- actions.Delete = () => {
- if (self.files.isReadOnly(key)) { return tooltip('cannot delete folder. ' + self.files.type + ' is a read only explorer') }
- const currentFoldername = extractNameFromKey(key)
-
- modalDialogCustom.confirm('Confirm to delete folder', `Are you sure you want to delete ${currentFoldername} folder?`,
- async () => {
- const fileManager = self._deps.fileManager
- const removeFolder = await fileManager.remove(key)
-
- if (!removeFolder) {
- tooltip(`failed to remove ${key}. Make sure the directory is empty before removing it.`)
- }
- }, () => {})
- }
- if (folderPath === 'browser/gists') {
- actions['Push changes to gist'] = () => {
- const id = key.substr(key.lastIndexOf('/') + 1, key.length - 1)
- modalDialogCustom.confirm(
- 'Push back to Gist',
- 'Are you sure you want to push all your changes back to Gist?',
- () => { self.toGist(id) },
- () => {}
- )
- }
- }
- }
- MENU_HANDLE = contextMenu(event, actions)
- })
-
- self.treeView.event.register('leafRightClick', function (key, data, label, event) {
- if (key === self.files.type) return
- MENU_HANDLE && MENU_HANDLE.hide(null, true)
- const actions = {}
- const provider = self._deps.fileManager.fileProviderOf(key)
- if (!provider.isExternalFolder(key)) {
- actions['Create Folder'] = () => self.createNewFolder(self._deps.fileManager.extractPathOf(key))
- actions.Rename = () => {
- if (self.files.isReadOnly(key)) { return tooltip('cannot rename file. ' + self.files.type + ' is a read only explorer') }
- var name = label.querySelector('span[data-path="' + key + '"]')
- if (name) editModeOn(name)
- }
- actions.Delete = () => {
- if (self.files.isReadOnly(key)) { return tooltip('cannot delete file. ' + self.files.type + ' is a read only explorer') }
- const currentFilename = extractNameFromKey(key)
-
- modalDialogCustom.confirm(
- 'Delete file', `Are you sure you want to delete ${currentFilename} file?`,
- async () => {
- const fileManager = self._deps.fileManager
- const removeFile = await fileManager.remove(key)
-
- if (!removeFile) {
- tooltip(`Failed to remove file ${key}.`)
- }
- },
- () => {}
- )
- }
- if (key.endsWith('.js')) {
- actions.Run = async () => {
- provider.get(key, (error, content) => {
- if (error) return console.log(error)
- plugin.call('scriptRunner', 'execute', content)
- })
- }
- }
- }
- MENU_HANDLE = contextMenu(event, actions)
- })
-
- self.treeView.event.register('leafClick', function (key, data, label) {
- self.events.trigger('focus', [key])
- })
-
- self.treeView.event.register('nodeClick', function (path, childrenContainer) {
- if (!childrenContainer) return
- if (childrenContainer.style.display === 'none') return
- self.updatePath(path)
- })
-
- // register to main app, trigger when the current file in the editor changed
- self._deps.fileManager.events.on('currentFileChanged', (newFile) => {
- const provider = self._deps.fileManager.fileProviderOf(newFile)
- if (self.focusElement && self.focusPath !== newFile) {
- self.focusElement.classList.remove('bg-secondary')
- self.focusElement = null
- self.focusPath = null
- }
- if (provider && (provider.type === files.type)) {
- self.focusElement = self.treeView.labelAt(newFile)
- if (self.focusElement) {
- self.focusElement.classList.add('bg-secondary')
- self.focusPath = newFile
- }
- }
- })
-
- self._deps.fileManager.events.on('noFileSelected', () => {
- if (self.focusElement) {
- self.focusElement.classList.remove('bg-secondary')
- self.focusElement = null
- self.focusPath = null
- }
- })
-
- var textUnderEdit = null
-
- function selectElementContents (el) {
- var range = document.createRange()
- range.selectNodeContents(el)
- var sel = window.getSelection()
- sel.removeAllRanges()
- sel.addRange(range)
- }
-
- function editModeOn (label) {
- textUnderEdit = label.innerText
- label.setAttribute('contenteditable', true)
- label.classList.add('bg-light')
- label.focus()
- selectElementContents(label)
- }
-
- function editModeOff (event) {
- const label = this
-
- const isFolder = label.className.indexOf('folder') !== -1
- function rename () {
- var newPath = label.dataset.path
- newPath = newPath.split('/')
- newPath[newPath.length - 1] = label.innerText
- newPath = newPath.join('/')
- if (label.innerText === '') {
- modalDialogCustom.alert('File name cannot be empty')
- label.innerText = textUnderEdit
- } else if (helper.checkSpecialChars(label.innerText)) {
- modalDialogCustom.alert('Special characters are not allowed')
- label.innerText = textUnderEdit
- } else {
- files.exists(newPath, (error, exist) => {
- if (error) return modalDialogCustom.alert('Unexpected error while renaming: ' + error)
- if (!exist) {
- files.rename(label.dataset.path, newPath, isFolder)
- } else {
- modalDialogCustom.alert('File already exists.')
- label.innerText = textUnderEdit
- }
- })
- }
- }
-
- if (event.which === 13) event.preventDefault()
- if ((event.type === 'blur' || event.which === 13) && label.getAttribute('contenteditable')) {
- var save = textUnderEdit !== label.innerText
- if (save) {
- modalDialogCustom.confirm(
- 'Confirm to rename a ' + (isFolder ? 'folder' : 'file'),
- 'Are you sure you want to rename ' + textUnderEdit + '?',
- () => { rename() },
- () => { label.innerText = textUnderEdit }
- )
- }
- label.removeAttribute('contenteditable')
- label.classList.remove('bg-light')
- }
- }
-}
-
-fileExplorer.prototype.updatePath = function (path) {
- this.files.resolveDirectory(path, (error, fileTree) => {
- if (error) console.error(error)
- if (!fileTree) return
- var newTree = normalize(path, fileTree)
- this.treeView.updateNodeFromJSON(path, newTree, true)
- })
-}
-
-fileExplorer.prototype.hide = function () {
- if (this.container) this.container.style.display = 'none'
-}
-
-fileExplorer.prototype.show = function () {
- if (this.container) this.container.style.display = 'block'
-}
-
-fileExplorer.prototype.init = function () {
- this.container = yo``
- return this.container
-}
-
-fileExplorer.prototype.publishToGist = function () {
- modalDialogCustom.confirm(
- 'Create a public gist',
- 'Are you sure you want to publish all your files in browser directory anonymously as a public gist on github.com? Note: this will not include directories.',
- () => { this.toGist() }
- )
-}
-
-fileExplorer.prototype.uploadFile = function (event) {
- // TODO The file explorer is merely a view on the current state of
- // the files module. Please ask the user here if they want to overwrite
- // a file and then just use `files.add`. The file explorer will
- // pick that up via the 'fileAdded' event from the files module.
-
- const self = this
-
- ;[...event.target.files].forEach((file) => {
- const files = this.files
- function loadFile () {
- var fileReader = new FileReader()
- fileReader.onload = async function (event) {
- if (helper.checkSpecialChars(file.name)) {
- modalDialogCustom.alert('Special characters are not allowed')
- return
- }
- var success = await files.set(name, event.target.result)
- if (!success) {
- modalDialogCustom.alert('Failed to create file ' + name)
- } else {
- self.events.trigger('focus', [name])
- }
- }
- fileReader.readAsText(file)
- }
- var name = files.type + '/' + file.name
- files.exists(name, (error, exist) => {
- if (error) console.log(error)
- if (!exist) {
- loadFile()
- } else {
- modalDialogCustom.confirm('Confirm overwrite', `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() })
- }
- })
- })
-}
-
-fileExplorer.prototype.toGist = function (id) {
- const proccedResult = function (error, data) {
- if (error) {
- modalDialogCustom.alert('Failed to manage gist: ' + error)
- console.log('Failed to manage gist: ' + error)
- } else {
- if (data.html_url) {
- modalDialogCustom.confirm('Gist is ready', `The gist is at ${data.html_url}. Would you like to open it in a new window?`, () => {
- window.open(data.html_url, '_blank')
- })
- } else {
- modalDialogCustom.alert(data.message + ' ' + data.documentation_url + ' ' + JSON.stringify(data.errors, null, '\t'))
- }
- }
- }
-
- /**
- * This function is to get the original content of given gist
- * @params id is the gist id to fetch
- */
- async function getOriginalFiles (id) {
- if (!id) {
- return []
- }
-
- const url = `https://api.github.com/gists/${id}`
- const res = await fetch(url)
- const data = await res.json()
- return data.files || []
- }
-
- // If 'id' is not defined, it is not a gist update but a creation so we have to take the files from the browser explorer.
- const folder = id ? '/gists/' + id : '/'
- this.packageFiles(this.files, folder, (error, packaged) => {
- if (error) {
- console.log(error)
- modalDialogCustom.alert('Failed to create gist: ' + error.message)
- } else {
- // check for token
- var tokenAccess = this._deps.config.get('settings/gist-access-token')
- if (!tokenAccess) {
- modalDialogCustom.alert(
- 'Remix requires an access token (which includes gists creation permission). Please go to the settings tab to create one.'
- )
- } else {
- const description = 'Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. \n Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=' +
- queryParams.get().version + '&optimize=' + queryParams.get().optimize + '&runs=' + queryParams.get().runs + '&gist='
- const gists = new Gists({ token: tokenAccess })
-
- if (id) {
- const originalFileList = getOriginalFiles(id)
- // Telling the GIST API to remove files
- const updatedFileList = Object.keys(packaged)
- const allItems = Object.keys(originalFileList)
- .filter(fileName => updatedFileList.indexOf(fileName) === -1)
- .reduce((acc, deleteFileName) => ({
- ...acc,
- [deleteFileName]: null
- }), originalFileList)
- // adding new files
- updatedFileList.forEach((file) => {
- const _items = file.split('/')
- const _fileName = _items[_items.length - 1]
- allItems[_fileName] = packaged[file]
- })
-
- tooltip('Saving gist (' + id + ') ...')
- gists.edit({
- description: description,
- public: true,
- files: allItems,
- id: id
- }, (error, result) => {
- proccedResult(error, result)
- if (!error) {
- for (const key in allItems) {
- if (allItems[key] === null) delete allItems[key]
- }
- }
- })
- } else {
- // id is not existing, need to create a new gist
- tooltip('Creating a new gist ...')
- gists.create({
- description: description,
- public: true,
- files: packaged
- }, (error, result) => {
- proccedResult(error, result)
- })
- }
- }
- }
- })
-}
-
-// return all the files, except the temporary/readonly ones..
-fileExplorer.prototype.packageFiles = function (filesProvider, directory, callback) {
- const ret = {}
- filesProvider.resolveDirectory(directory, (error, files) => {
- if (error) callback(error)
- else {
- async.eachSeries(Object.keys(files), (path, cb) => {
- if (filesProvider.isDirectory(path)) {
- cb()
- } else {
- filesProvider.get(path, (error, content) => {
- if (error) return cb(error)
- if (/^\s+$/.test(content) || !content.length) {
- content = '// this line is added to create a gist. Empty file is not allowed.'
- }
- ret[path] = { content }
- cb()
- })
- }
- }, (error) => {
- callback(error, ret)
- })
- }
- })
-}
-
-fileExplorer.prototype.createNewFile = function (parentFolder = '/') {
- const self = this
- modalDialogCustom.prompt('Create new file', 'File Name (e.g Untitled.sol)', 'Untitled.sol', (input) => {
- if (!input) input = 'New file'
- helper.createNonClashingName(parentFolder + '/' + input, self.files, async (error, newName) => {
- if (error) return tooltip('Failed to create file ' + newName + ' ' + error)
- const fileManager = self._deps.fileManager
- const createFile = await fileManager.writeFile(newName, '')
-
- if (!createFile) {
- tooltip('Failed to create file ' + newName)
- } else {
- await fileManager.open(newName)
- if (newName.includes('_test.sol')) {
- self.events.trigger('newTestFileCreated', [newName])
- }
- }
- })
- }, null, true)
-}
-
-fileExplorer.prototype.createNewFolder = function (parentFolder) {
- const self = this
- modalDialogCustom.prompt('Create new folder', '', 'New folder', (input) => {
- if (!input) {
- return tooltip('Failed to create folder. The name can not be empty')
- }
-
- const currentPath = !parentFolder ? self._deps.fileManager.currentPath() : parentFolder
- let newName = currentPath ? currentPath + '/' + input : self.files.type + '/' + input
-
- newName = newName + '/'
- self.files.exists(newName, (error, exist) => {
- if (error) return tooltip('Unexpected error while creating folder: ' + error)
- if (!exist) {
- self.files.set(newName, '')
- } else {
- tooltip('Folder already exists.', () => {})
- }
- })
- }, null, true)
-}
-
-fileExplorer.prototype.renderMenuItems = function () {
- let items = ''
- if (this.menuItems) {
- items = this.menuItems.map(({ action, title, icon }) => {
- if (action === 'uploadFile') {
- return yo`
-
- `
- } else {
- return yo`
- { event.stopPropagation(); this[action]() }}
- class="newFile ${icon} ${css.newFile}"
- title=${title}
- >
-
- `
- }
- })
- }
- return yo``
-}
-
-fileExplorer.prototype.ensureRoot = function (cb) {
- cb = cb || (() => {})
- var self = this
- if (self.element) return cb()
- const root = {}
- root[this.files.type] = {}
- var element = self.treeView.render(root, false)
- element.classList.add(css.fileexplorer)
- element.events = self.events
- element.api = self.api
- self.container.appendChild(element)
- self.element = element
- if (cb) cb()
- self.treeView.expand(self.files.type)
-}
-
-function normalize (path, filesList) {
- var prefix = path.split('/')[0]
- var newList = {}
- Object.keys(filesList).forEach(key => {
- newList[prefix + '/' + key] = filesList[key].isDirectory ? {} : { '/content': true }
- })
- return newList
-}
-
-module.exports = fileExplorer
diff --git a/apps/remix-ide/src/app/tabs/compile-tab.js b/apps/remix-ide/src/app/tabs/compile-tab.js
index 285ecb5363..6d84a9721f 100644
--- a/apps/remix-ide/src/app/tabs/compile-tab.js
+++ b/apps/remix-ide/src/app/tabs/compile-tab.js
@@ -24,7 +24,6 @@ const profile = {
documentation: 'https://remix-ide.readthedocs.io/en/latest/solidity_editor.html',
version: packageJson.version,
methods: ['getCompilationResult', 'compile', 'compileWithParameters', 'setCompilerConfig', 'compileFile']
-
}
// EditorApi:
diff --git a/apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js b/apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js
deleted file mode 100644
index a7214c3b3a..0000000000
--- a/apps/remix-ide/src/app/tabs/compileTab/compilerContainer.js
+++ /dev/null
@@ -1,580 +0,0 @@
-
-import toaster from '../../ui/tooltip'
-import { canUseWorker, baseURLBin, baseURLWasm, urlFromVersion, pathToURL, promisedMiniXhr } from '@remix-project/remix-solidity'
-const yo = require('yo-yo')
-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')
-const _paq = window._paq = window._paq || []
-
-class CompilerContainer {
- constructor (compileTabLogic, editor, config, queryParams) {
- this._view = {}
- this.compileTabLogic = compileTabLogic
- this.editor = editor
- this.config = config
- this.queryParams = queryParams
- this.hhCompilation = false
-
- this.data = {
- hideWarnings: config.get('hideWarnings') || false,
- autoCompile: config.get('autoCompile'),
- compileTimeout: null,
- timeout: 300,
- allversions: null,
- selectedVersion: null,
- defaultVersion: 'soljson-v0.8.4+commit.c7e474f2.js' // this default version is defined: in makeMockCompiler (for browser test)
- }
- }
-
- /**
- * Update the compilation button with the name of the current file
- */
- set currentFile (name = '') {
- if (name && name !== '') {
- this._setCompilerVersionFromPragma(name)
- }
- if (!this._view.compilationButton) return
- const button = this.compilationButton(name.split('/').pop())
- this._disableCompileBtn(!name || (name && !this.isSolFileSelected(name)))
- yo.update(this._view.compilationButton, button)
- }
-
- isSolFileSelected (currentFile = '') {
- if (!currentFile) currentFile = this.config.get('currentFile')
- if (!currentFile) return false
- const extention = currentFile.substr(currentFile.length - 3, currentFile.length)
- return extention.toLowerCase() === 'sol' || extention.toLowerCase() === 'yul'
- }
-
- deactivate () {
- // deactivate editor listeners
- this.editor.event.unregister('contentChanged')
- this.editor.event.unregister('sessionSwitched')
- }
-
- activate () {
- this.currentFile = this.config.get('currentFile')
- this.listenToEvents()
- }
-
- listenToEvents () {
- this.editor.event.register('sessionSwitched', () => {
- if (!this._view.compileIcon) return
- this.scheduleCompilation()
- })
-
- this.compileTabLogic.event.on('startingCompilation', () => {
- if (!this._view.compileIcon) return
- this._view.compileIcon.setAttribute('title', 'compiling...')
- this._view.compileIcon.classList.remove(`${css.bouncingIcon}`)
- this._view.compileIcon.classList.add(`${css.spinningIcon}`)
- })
-
- this.compileTabLogic.compiler.event.register('compilationDuration', (speed) => {
- if (!this._view.warnCompilationSlow) return
- if (speed > 1000) {
- const msg = `Last compilation took ${speed}ms. We suggest to turn off autocompilation.`
- this._view.warnCompilationSlow.setAttribute('title', msg)
- this._view.warnCompilationSlow.style.visibility = 'visible'
- } else {
- this._view.warnCompilationSlow.style.visibility = 'hidden'
- }
- })
-
- this.editor.event.register('contentChanged', () => {
- if (!this._view.compileIcon) return
- this.scheduleCompilation()
- this._view.compileIcon.classList.add(`${css.bouncingIcon}`) // @TODO: compileView tab
- })
-
- this.compileTabLogic.compiler.event.register('loadingCompiler', () => {
- if (!this._view.compileIcon) return
- this._disableCompileBtn(true)
- this._view.compileIcon.setAttribute('title', 'compiler is loading, please wait a few moments.')
- this._view.compileIcon.classList.add(`${css.spinningIcon}`)
- this._view.warnCompilationSlow.style.visibility = 'hidden'
- this._updateLanguageSelector()
- })
-
- this.compileTabLogic.compiler.event.register('compilerLoaded', () => {
- if (!this._view.compileIcon) return
- this._disableCompileBtn(false)
- this._view.compileIcon.setAttribute('title', '')
- this._view.compileIcon.classList.remove(`${css.spinningIcon}`)
- if (this.data.autoCompile) this.compileIfAutoCompileOn()
- })
-
- this.compileTabLogic.compiler.event.register('compilationFinished', (success, data, source) => {
- if (!this._view.compileIcon) return
- this._view.compileIcon.setAttribute('title', 'idle')
- this._view.compileIcon.classList.remove(`${css.spinningIcon}`)
- this._view.compileIcon.classList.remove(`${css.bouncingIcon}`)
- _paq.push(['trackEvent', 'compiler', 'compiled_with_version', this._retrieveVersion()])
- })
- }
-
- /**************
- * SUBCOMPONENT
- */
- compilationButton (name = '') {
- const displayed = name || ''
- const disabled = name && this.isSolFileSelected() ? '' : 'disabled'
- return yo`
-
- `
- }
-
- _disableCompileBtn (shouldDisable) {
- const btn = document.getElementById('compileBtn')
- if (!btn) return
- if (shouldDisable) {
- btn.classList.add('disabled')
- } else if (this.isSolFileSelected()) {
- btn.classList.remove('disabled')
- }
- }
-
- // Load solc compiler version according to pragma in contract file
- _setCompilerVersionFromPragma (filename) {
- if (!this.data.allversions) return
- this.compileTabLogic.fileManager.readFile(filename).then(data => {
- const pragmaArr = data.match(/(pragma solidity (.+?);)/g)
- if (pragmaArr && pragmaArr.length === 1) {
- const pragmaStr = pragmaArr[0].replace('pragma solidity', '').trim()
- const pragma = pragmaStr.substring(0, pragmaStr.length - 1)
- const releasedVersions = this.data.allversions.filter(obj => !obj.prerelease).map(obj => obj.version)
- const allVersions = this.data.allversions.map(obj => this._retrieveVersion(obj.version))
- const currentCompilerName = this._retrieveVersion(this._view.versionSelector.selectedOptions[0].label)
- // contains only numbers part, for example '0.4.22'
- const pureVersion = this._retrieveVersion()
- // is nightly build newer than the last release
- const isNewestNightly = currentCompilerName.includes('nightly') && semver.gt(pureVersion, releasedVersions[0])
- // checking if the selected version is in the pragma range
- const isInRange = semver.satisfies(pureVersion, pragma)
- // checking if the selected version is from official compilers list(excluding custom versions) and in range or greater
- const isOfficial = allVersions.includes(currentCompilerName)
- if (isOfficial && (!isInRange && !isNewestNightly)) {
- const compilerToLoad = semver.maxSatisfying(releasedVersions, pragma)
- const compilerPath = this.data.allversions.filter(obj => !obj.prerelease && obj.version === compilerToLoad)[0].path
- if (this.data.selectedVersion !== compilerPath) {
- this.data.selectedVersion = compilerPath
- this._updateVersionSelector()
- }
- }
- }
- })
- }
-
- _retrieveVersion (version) {
- if (!version) version = this._view.versionSelector.value
- if (version === 'builtin') version = this.data.defaultVersion
- return semver.coerce(version) ? semver.coerce(version).version : ''
- }
-
- render () {
- this.compileTabLogic.compiler.event.register('compilerLoaded', (version) => this.setVersionText(version))
- this.fetchAllVersion((allversions, selectedVersion, isURL) => {
- this.data.allversions = allversions
- if (isURL) this._updateVersionSelector(selectedVersion)
- else {
- this.data.selectedVersion = selectedVersion
- if (this._view.versionSelector) this._updateVersionSelector()
- }
- })
-
- this.hardhatCompilation = yo`
- this.updatehhCompilation(e)} id="enableHardhat" type="checkbox" title="Enable Hardhat Compilation">
-
-
`
- this._view.warnCompilationSlow = yo``
- this._view.compileIcon = yo``
- this._view.autoCompile = yo` this.updateAutoCompile()} data-id="compilerContainerAutoCompile" id="autoCompile" type="checkbox" title="Auto compile">`
- this._view.hideWarningsBox = yo` this.hideWarnings()} id="hideWarningsBox" type="checkbox" title="Hide warnings">`
- if (this.data.autoCompile) this._view.autoCompile.setAttribute('checked', '')
- if (this.data.hideWarnings) this._view.hideWarningsBox.setAttribute('checked', '')
-
- this._view.optimize = yo` this.onchangeOptimize()} class="custom-control-input" id="optimize" type="checkbox">`
- if (this.compileTabLogic.optimize) this._view.optimize.setAttribute('checked', '')
-
- this._view.runs = yo` this.onchangeRuns()}
- >`
- if (this.compileTabLogic.optimize) {
- this._view.runs.removeAttribute('disabled')
- this._view.runs.value = this.compileTabLogic.runs
- } else {
- this._view.runs.setAttribute('disabled', '')
- }
-
- this._view.versionSelector = yo`
- `
- this._view.languageSelector = yo`
- `
- this._view.version = yo``
-
- this._view.evmVersionSelector = yo`
- `
- if (this.compileTabLogic.evmVersion) {
- const s = this._view.evmVersionSelector
- let i
- for (i = 0; i < s.options.length; i++) {
- if (s.options[i].value === this.compileTabLogic.evmVersion) {
- break
- }
- }
- if (i === s.options.length) { // invalid evmVersion from queryParams
- s.selectedIndex = 0 // compiler default
- this.onchangeEvmVersion()
- } else {
- s.selectedIndex = i
- this.onchangeEvmVersion()
- }
- }
-
- this._view.compilationButton = this.compilationButton()
-
- this._view.includeNightlies = yo`
- this._updateVersionSelector()}>
- `
- this._view.compileContainer = yo`
-
-
-
-
-
-
- ${this._view.versionSelector}
-
-
- ${this._view.includeNightlies}
-
-
-
-
- ${this._view.languageSelector}
-
-
-
- ${this._view.evmVersionSelector}
-
-
-
Compiler Configuration
-
- ${this._view.autoCompile}
-
-
-
-
- ${this._view.optimize}
-
- ${this._view.runs}
-
-
-
- ${this._view.hideWarningsBox}
-
-
-
- ${this.hardhatCompilation}
- ${this._view.compilationButton}
-
-
-
- `
-
- return this._view.compileContainer
- }
-
- promtCompiler () {
- modalDialogCustom.prompt(
- 'Add a custom compiler',
- 'URL',
- '',
- (url) => this.addCustomCompiler(url)
- )
- }
-
- addCustomCompiler (url) {
- this.data.selectedVersion = this._view.versionSelector.value
- this._updateVersionSelector(url)
- }
-
- updateAutoCompile (event) {
- this.config.set('autoCompile', this._view.autoCompile.checked)
- }
-
- updatehhCompilation (event) {
- this.hhCompilation = event.target.checked
- }
-
- compile (event) {
- const currentFile = this.config.get('currentFile')
- if (!this.isSolFileSelected()) return
-
- this._setCompilerVersionFromPragma(currentFile)
- this.compileTabLogic.runCompiler(this.hhCompilation)
- }
-
- compileIfAutoCompileOn () {
- if (this.config.get('autoCompile')) {
- this.compile()
- }
- }
-
- hideWarnings (event) {
- this.config.set('hideWarnings', this._view.hideWarningsBox.checked)
- this.compileIfAutoCompileOn()
- }
-
- /*
- The following functions are handlers for internal events.
- */
-
- onchangeOptimize () {
- this.compileTabLogic.setOptimize(!!this._view.optimize.checked)
- if (this.compileTabLogic.optimize) {
- this._view.runs.removeAttribute('disabled')
- this.compileTabLogic.setRuns(parseInt(this._view.runs.value))
- } else {
- this.compileTabLogic.setRuns(200)
- this._view.runs.setAttribute('disabled', '')
- }
- this.compileIfAutoCompileOn()
- }
-
- onchangeRuns () {
- this.compileTabLogic.setRuns(parseInt(this._view.runs.value))
- this.compileIfAutoCompileOn()
- }
-
- onchangeLanguage () {
- this.compileTabLogic.setLanguage(this._view.languageSelector.value)
- this.compileIfAutoCompileOn()
- }
-
- onchangeEvmVersion () {
- const s = this._view.evmVersionSelector
- let v = s.value
- if (v === 'default') {
- v = null
- }
- this.compileTabLogic.setEvmVersion(v)
- for (let i = 0; i < s.options.length; i++) {
- if (i === s.selectedIndex) {
- s.options[s.selectedIndex].setAttribute('selected', 'selected')
- } else {
- s.options[i].removeAttribute('selected')
- }
- }
-
- this.compileIfAutoCompileOn()
- }
-
- onchangeLoadVersion () {
- this.data.selectedVersion = this._view.versionSelector.value
- this._updateVersionSelector()
- this._updateLanguageSelector()
- }
-
- /*
- The following functions map with the above event handlers.
- They are an external API for modifying the compiler configuration.
- */
- setConfiguration (settings) {
- this.setLanguage(settings.language)
- this.setEvmVersion(settings.evmVersion)
- this.setOptimize(settings.optimize)
- this.setRuns(settings.runs)
- this.setVersion(settings.version)
- }
-
- setOptimize (enabled) {
- this._view.optimize.checked = enabled
- this.onchangeOptimize()
- }
-
- setRuns (value) {
- if (value) {
- this._view.runs.value = value
- this.onchangeRuns()
- }
- }
-
- setLanguage (lang) {
- this._view.languageSelector.value = lang
- this.onchangeLanguage()
- }
-
- setEvmVersion (version) {
- this._view.evmVersionSelector.value = version || 'default'
- this.onchangeEvmVersion()
- }
-
- setVersion (version) {
- this._view.versionSelector.value = `soljson-v${version}.js`
- this.onchangeLoadVersion()
- }
-
- _shouldBeAdded (version) {
- return !version.includes('nightly') ||
- (version.includes('nightly') && this._view.includeNightlies.checked)
- }
-
- _updateVersionSelector (customUrl = '') {
- // update selectedversion if previous one got filtered out
- if (!this.data.selectedVersion || !this._shouldBeAdded(this.data.selectedVersion)) {
- this.data.selectedVersion = this.data.defaultVersion
- }
- this._view.versionSelector.innerHTML = ''
- this._view.versionSelector.removeAttribute('disabled')
- this.queryParams.update({ version: this.data.selectedVersion })
- let url
- if (customUrl !== '') {
- this.data.selectedVersion = customUrl
- this._view.versionSelector.appendChild(yo``)
- url = customUrl
- this.queryParams.update({ version: this.data.selectedVersion })
- } else if (this.data.selectedVersion === 'builtin') {
- let location = window.document.location
- let path = location.pathname
- if (!path.startsWith('/')) path = '/' + path
- location = `${location.protocol}//${location.host}${path}assets/js`
- if (location.endsWith('index.html')) location = location.substring(0, location.length - 10)
- if (!location.endsWith('/')) location += '/'
- url = location + 'soljson.js'
- } else {
- if (this.data.selectedVersion.indexOf('soljson') !== 0 || helper.checkSpecialChars(this.data.selectedVersion)) {
- return console.log('loading ' + this.data.selectedVersion + ' not allowed')
- }
- url = `${urlFromVersion(this.data.selectedVersion)}`
- }
-
- this.data.allversions.forEach(build => {
- const option = build.path === this.data.selectedVersion
- ? yo``
- : yo``
-
- if (this._shouldBeAdded(option.innerText)) {
- this._view.versionSelector.appendChild(option)
- }
- })
- if (this.data.selectedVersion !== 'builtin' && semver.lt(this._retrieveVersion(), 'v0.4.12+commit.194ff033.js')) {
- toaster(yo`
-
-
Old compiler usage detected.
-
You are using a compiler older than v0.4.12.
-
Some functionality may not work.
-
`
- )
- }
-
- // 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._retrieveVersion())) {
- this.compileTabLogic.compiler.loadVersion(true, url)
- this.setVersionText('(loading using worker)')
- } else {
- this.compileTabLogic.compiler.loadVersion(false, url)
- this.setVersionText('(loading)')
- }
- }
-
- _updateLanguageSelector () {
- // This is the first version when Yul is available
- if (!semver.valid(this._retrieveVersion()) || semver.lt(this._retrieveVersion(), 'v0.5.7+commit.6da8b019.js')) {
- this._view.languageSelector.setAttribute('disabled', '')
- this._view.languageSelector.value = 'Solidity'
- this.compileTabLogic.setLanguage('Solidity')
- } else {
- this._view.languageSelector.removeAttribute('disabled')
- }
- }
-
- setVersionText (text) {
- if (this._view.version) this._view.version.innerText = text
- }
-
- // fetching both normal and wasm builds and creating a [version, baseUrl] map
- async fetchAllVersion (callback) {
- let selectedVersion, allVersionsWasm, isURL
- let allVersions = [{ path: 'builtin', longVersion: 'Stable local version - 0.8.4' }]
- // 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') {
- selectedVersion = 'builtin'
- return callback(allVersions, selectedVersion)
- }
- try {
- const versions = JSON.parse(binRes.json).builds.slice().reverse()
- allVersions = [...allVersions, ...versions]
- selectedVersion = this.data.defaultVersion
- if (this.queryParams.get().version) selectedVersion = this.queryParams.get().version
- // Check if version is a URL and corresponding filename starts with 'soljson'
- if (selectedVersion.startsWith('https://')) {
- const urlArr = selectedVersion.split('/')
- if (urlArr[urlArr.length - 1].startsWith('soljson')) isURL = true
- }
- if (wasmRes.event.type !== 'error') {
- allVersionsWasm = JSON.parse(wasmRes.json).builds.slice().reverse()
- }
- } 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, isURL)
- }
-
- scheduleCompilation () {
- if (!this.config.get('autoCompile')) return
- if (this.data.compileTimeout) window.clearTimeout(this.data.compileTimeout)
- this.data.compileTimeout = window.setTimeout(() => this.compileIfAutoCompileOn(), this.data.timeout)
- }
-}
-
-module.exports = CompilerContainer
diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-abstract.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-abstract.ts
deleted file mode 100644
index f0c4fc3ad1..0000000000
--- a/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-abstract.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-'use strict'
-import * as remixLib from '@remix-project/remix-lib'
-
-const txHelper = remixLib.execution.txHelper
-
-export class CompilerAbstract {
- public languageversion: string
- public data: Record
- public source: Record
-
- constructor (languageversion, data, source) {
- this.languageversion = languageversion
- this.data = data
- this.source = source // source code
- }
-
- 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
- }
-
- getAsts () {
- return this.data.sources // ast
- }
-
- getSourceName (fileIndex) {
- if (this.data && this.data.sources) {
- return Object.keys(this.data.sources)[fileIndex]
- } else if (Object.keys(this.source.sources).length === 1) {
- // if we don't have ast, we return the only one filename present.
- const sourcesArray = Object.keys(this.source.sources)
- return sourcesArray[0]
- }
- return null
- }
-
- getSourceCode () {
- return this.source
- }
-}
diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-helpers.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-helpers.ts
deleted file mode 100644
index 64c56bd7a5..0000000000
--- a/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-helpers.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict'
-import { canUseWorker, urlFromVersion } from './compiler-utils'
-import { Compiler } from '@remix-project/remix-solidity'
-import { CompilerAbstract } from './compiler-abstract'
-
-export const compile = async (compilationTargets, settings, contentResolverCallback) => {
- return new Promise((resolve) => {
- const compiler = new Compiler(contentResolverCallback)
- compiler.set('evmVersion', settings.evmVersion)
- compiler.set('optimize', settings.optimize)
- compiler.set('language', settings.language)
- compiler.set('runs', settings.runs)
- compiler.loadVersion(canUseWorker(settings.version), urlFromVersion(settings.version))
- compiler.event.register('compilationFinished', (success, compilationData, source) => {
- resolve(new CompilerAbstract(settings.version, compilationData, source))
- })
- compiler.event.register('compilerLoaded', () => compiler.compile(compilationTargets, ''))
- })
-}
diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-utils.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-utils.ts
deleted file mode 100644
index fe26765ac1..0000000000
--- a/libs/remix-ui/solidity-compiler/src/lib/logic/compiler-utils.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-const semver = require('semver')
-const minixhr = require('minixhr')
-/* global Worker */
-
-export const baseURLBin = 'https://binaries.soliditylang.org/bin'
-export const baseURLWasm = 'https://binaries.soliditylang.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) {
- 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) {
- const version = semver.coerce(selectedVersion)
- const isNightly = selectedVersion.includes('nightly')
- return browserSupportWorker() && (
- // All compiler versions (including nightlies) after 0.6.3 are wasm compiled
- semver.gt(version, '0.6.3') ||
- // Only releases are wasm compiled starting with 0.3.6
- (semver.gte(version, '0.3.6') && !isNightly)
- )
-}
-
-function browserSupportWorker () {
- return document.location.protocol !== 'file:' && Worker !== undefined
-}
-
-// returns a promise for minixhr
-export function promisedMiniXhr (url) {
- return new Promise((resolve) => {
- minixhr(url, (json, event) => {
- resolve({ json, event })
- })
- })
-}
diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/index.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/index.ts
index b67d648896..e2c8f6d006 100644
--- a/libs/remix-ui/solidity-compiler/src/lib/logic/index.ts
+++ b/libs/remix-ui/solidity-compiler/src/lib/logic/index.ts
@@ -1,5 +1,2 @@
export * from './compileTabLogic'
-export * from './compiler-abstract'
-export * from './compiler-helpers'
-export * from './compiler-utils'
export * from './contract-parser'