From 0af589dea155b88efac4b433d63710f9fb46457b Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Thu, 21 Jun 2018 19:06:55 +0200 Subject: [PATCH 01/14] Download network (registry) dapps and load them from filesystem --- electron/index.js | 28 ++-- package.json | 3 + src/Dapp/dapp.css | 23 +++ src/Dapp/dapp.js | 29 ++-- src/Dapps/store.js | 16 ++- src/inject.js | 8 +- src/util/dapps.js | 104 ++++++-------- src/util/hashFetch/expoRetry.js | 118 +++++++++++++++ src/util/hashFetch/index.js | 247 ++++++++++++++++++++++++++++++++ src/util/host.js | 11 +- webpack/app.js | 4 +- 11 files changed, 490 insertions(+), 101 deletions(-) create mode 100644 src/util/hashFetch/expoRetry.js create mode 100644 src/util/hashFetch/index.js diff --git a/electron/index.js b/electron/index.js index a1c5f9ba4..3c1884314 100644 --- a/electron/index.js +++ b/electron/index.js @@ -15,10 +15,9 @@ // along with Parity. If not, see . const electron = require('electron'); -const fs = require('fs'); const path = require('path'); const url = require('url'); -const util = require('util'); +const { ensureDir: fsEnsureDir } = require('fs-extra'); const addMenu = require('./menu'); const { cli } = require('./cli'); @@ -32,11 +31,16 @@ const { name: appName } = require('../package.json'); const { app, BrowserWindow, ipcMain, session } = electron; -const fsExists = util.promisify(fs.stat); // eslint-disable-line -const fsMkdir = util.promisify(fs.mkdir); - let mainWindow; +function runApp () { + doesParityExist() + .catch(() => fetchParity(mainWindow)) // Install parity if not present + .catch(handleError); // Errors should be handled before, this is really just in case + + return fsEnsureDir(getLocalDappsPath()).then(createWindow); +} + function createWindow () { // Will send these variables to renderers via IPC global.dirName = __dirname; @@ -45,18 +49,10 @@ function createWindow () { mainWindow = new BrowserWindow({ height: 800, - width: 1200 + width: 1200, + webPreferences: { nodeIntegrationInWorker: true } }); - const localDappsPath = getLocalDappsPath(); - - fsExists(localDappsPath) - .catch(() => fsMkdir(localDappsPath)); - - doesParityExist() - .catch(() => fetchParity(mainWindow)) // Install parity if not present - .catch(handleError); // Errors should be handled before, this is really just in case - if (cli.uiDev === true) { // Opens http://127.0.0.1:3000 in --ui-dev mode mainWindow.loadURL('http://127.0.0.1:3000'); @@ -122,7 +118,7 @@ function createWindow () { }); } -app.on('ready', createWindow); +app.on('ready', runApp); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { diff --git a/package.json b/package.json index 2f88e4290..8f1805e0e 100644 --- a/package.json +++ b/package.json @@ -169,6 +169,8 @@ "command-exists": "1.2.2", "commander": "2.15.1", "electron-dl": "1.11.0", + "follow-redirects": "1.5.0", + "fs-extra": "6.0.1", "is-electron": "2.1.0", "keythereum": "1.0.2", "lodash.flatten": "4.4.0", @@ -194,6 +196,7 @@ "semantic-ui-react": "0.77.0", "solc": "ngotchac/solc-js", "store": "1.3.20", + "unzipper": "0.8.14", "util.promisify": "1.0.0" } } diff --git a/src/Dapp/dapp.css b/src/Dapp/dapp.css index 3cd0684d4..482b31b36 100644 --- a/src/Dapp/dapp.css +++ b/src/Dapp/dapp.css @@ -31,4 +31,27 @@ font-family: 'Roboto', sans-serif; font-size: 16px; font-weight: 300; + display: flex; + align-items: center; + justify-content: center; + font-size: 2em; + color: #999; } + +.loading { + opacity: 0; + animation-duration: .5s; + animation-name: fadeIn; + animation-delay: 1.5s; + animation-fill-mode: forwards; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + diff --git a/src/Dapp/dapp.js b/src/Dapp/dapp.js index 9b796b803..084952c2b 100644 --- a/src/Dapp/dapp.js +++ b/src/Dapp/dapp.js @@ -149,39 +149,36 @@ export default class Dapp extends Component { } render () { - const { dappsUrl } = this.context.api; const { params } = this.props; const { app, loading } = this.state; if (loading) { - return null; + return ( +
+

+ +

+
+ ); } if (!app) { return (
-
+

-

+

); } - let src = null; - - switch (app.type) { - case 'local': - case 'builtin': - src = `${app.localUrl}?appId=${app.id}`; - break; - - case 'network': - src = `${dappsUrl}/${app.contentHash}/`; - break; - } + let src = `${app.localUrl}?appId=${app.id}`; let hash = ''; diff --git a/src/Dapps/store.js b/src/Dapps/store.js index c309e0e51..f65e3157e 100644 --- a/src/Dapps/store.js +++ b/src/Dapps/store.js @@ -20,6 +20,7 @@ import store from 'store'; import Contracts from '@parity/shared/lib/contracts'; import { fetchBuiltinApps, fetchLocalApps, fetchRegistryAppIds, fetchRegistryApp, subscribeToChanges } from '../util/dapps'; +import HashFetch from '../util/hashFetch'; const LS_KEY_DISPLAY = 'displayApps'; const LS_KEY_EXTERNAL_ACCEPT = 'acceptExternal'; @@ -123,6 +124,17 @@ export default class DappsStore extends EventEmitter { return this.fetchRegistryApp(dappReg, id, true); }) + .then((app) => { + if (app.type === 'network') { + return HashFetch.get().fetch(this._api, app.contentHash, 'dapp') + .then(appPath => { + app.localUrl = `file://${appPath}/index.html`; + return app; + }) + .catch(e => { console.error(`Error loading dapp ${id}`, e); }); + } + return app; + }) .then((app) => { this.emit('loaded', app); return app; @@ -240,7 +252,9 @@ export default class DappsStore extends EventEmitter { }); return Promise.all(promises); - }); + }) + .then(apps => + apps.filter(app => app)); } @action refreshDapps = () => { diff --git a/src/inject.js b/src/inject.js index e12d8ac78..edbce314f 100644 --- a/src/inject.js +++ b/src/inject.js @@ -18,19 +18,15 @@ import Api from '@parity/api'; import qs from 'query-string'; function getAppId () { - // Local dapps: file:///home/username/.config/Parity-UI/dapps/mydapp/index.html?appId=LOCAL-dapp-name + // Local dapps: file:///home/username/.config/parity-ui/dapps/mydapp/index.html?appId=LOCAL-dapp-name // Local dapps served in development mode on a dedicated port: http://localhost:3001/?appId=LOCAL-dapp-name // Built-in dapps: file://path-to-shell/.build/dapps/0x0587.../index.html?appId=dapp-name // Built-in dapps when running Electron in dev mode: http://127.0.0.1:3000/dapps/v1/index.html?appId=dapp-name + // Network dapps: file:///home/username/.config/parity-ui/hashfetch/files/0x8075.../index.html?appId=dapp-name const fromQuery = qs.parse(window.location.search).appId; if (fromQuery) { return fromQuery; } - // Dapps installed from the registry and served by Parity: http://127.0.0.1:8545/ff19... - const [hash] = window.location.pathname.match(/(0x)?[a-f0-9]{64}/i) || []; - - if (hash) { return hash; } - console.error('Could not find appId'); } diff --git a/src/util/dapps.js b/src/util/dapps.js index bcebbbacb..2f549b86b 100644 --- a/src/util/dapps.js +++ b/src/util/dapps.js @@ -15,11 +15,11 @@ // along with Parity. If not, see . import BigNumber from 'bignumber.js'; -import { pick, range, uniq } from 'lodash'; +import { range, uniq } from 'lodash'; import { bytesToHex } from '@parity/api/lib/util/format'; -import { IconCache } from '@parity/ui'; import { getBuildPath, getLocalDappsPath } from './host'; +import HashFetch from './hashFetch'; import isElectron from 'is-electron'; import builtinApps from '../Dapps/dappsBuiltin.json'; @@ -200,6 +200,7 @@ export function fetchRegistryAppIds (api) { }); } +// Returns undefined if dapp is invalid export function fetchRegistryApp (api, dappReg, appId) { return Promise .all([ @@ -208,63 +209,50 @@ export function fetchRegistryApp (api, dappReg, appId) { dappReg.getManifest(appId) ]) .then(([imageId, contentId, manifestId]) => { - const app = { - id: appId, - image: IconCache.hashToImage(imageId), - contentHash: bytesToHex(contentId).substr(2), - manifestHash: bytesToHex(manifestId).substr(2), - type: 'network', - visible: true - }; - - return fetchManifest(api, app.manifestHash) - .then((manifest) => { - if (manifest) { - app.manifestHash = null; - - // Add usefull manifest fields to app - Object.assign(app, pick(manifest, ['author', 'description', 'name', 'version'])); - } - - return app; - }); - }) - .then((app) => { - // Keep dapps that has a Manifest File and an Id - const dapp = (app.manifestHash || !app.id) ? null : app; - - return dapp; - }) - .catch((error) => { - console.warn('DappsStore:fetchRegistryApp', error); - }); -} - -export function fetchManifest (api, manifestHash) { - if (/^(0x)?0+/.test(manifestHash)) { - return Promise.resolve(null); - } - - return api.parity - .dappsUrl() - .then(dappsUrl => { - const protocol = window.location.protocol === 'https:' ? 'https:' : 'http:'; + const imageHash = bytesToHex(imageId).substr(2); + const contentHash = bytesToHex(contentId).substr(2); + const manifestHash = bytesToHex(manifestId).substr(2); + + return Promise.all([ + HashFetch.get().fetch(api, imageHash, 'file').catch((e) => { console.warn(`Couldn't download icon for dapp ${appId}`, e); }), + HashFetch.get().fetch(api, manifestHash, 'file').catch((e) => { throw new Error(`Couldn't download manifest ${e.toString()}`); }) + ]).then(([imagePath, manifestPath]) => + fsReadFile(manifestPath) + .then(manifestJson => { + try { + const manifest = JSON.parse(manifestJson); + + if (!manifest.id) { + throw new Error(`Missing app id in manifest.json ${manifest}`); + } - return fetch( - `${protocol}//${dappsUrl}/api/content/${manifestHash}/`, - { redirect: 'follow', mode: 'cors' } + return manifest; + } catch (e) { + throw new Error(`Couldn't parse manifest.json ${e}`); + } + }) + .catch(e => { + throw new Error(`Couldn't read manifest.json file locally (${manifestPath}) ${e}`); + }) + .then(manifest => { + const { author, description, name, version } = manifest; + const app = { + id: appId, + type: 'network', + author, + description, + name: name || '', + version, + visible: true, // Display by default + image: `file://${imagePath}`, + contentHash + }; + + return app; + }) ); }) - .then((response) => { - return response.ok - ? response.json() - : null; - }) - .then((manifest) => { - return manifest; - }) - .catch((error) => { - console.warn('DappsStore:fetchManifest', error); - return null; - }); + .catch((error) => { + console.warn('DappsStore:fetchRegistryApp', appId, error); + }); } diff --git a/src/util/hashFetch/expoRetry.js b/src/util/hashFetch/expoRetry.js new file mode 100644 index 000000000..64133fecd --- /dev/null +++ b/src/util/hashFetch/expoRetry.js @@ -0,0 +1,118 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +const fs = window.require('fs'); +const util = window.require('util'); +const path = window.require('path'); + +import { readJson as fsReadJson, writeJson as fsWriteJson } from 'fs-extra'; +const fsExists = util.promisify(fs.stat); + +import { getHashFetchPath } from '../host'; + +// Handle retries with exponential delay for failed download attempts +export default class ExpoRetry { + static instance = null; + + // We store the URL to allow GH Hint URL updates for a given hash + // to take effect immediately, and to disregard past failed attempts at + // getting this file from other URLs. + // { + // [`${hash}:${url}`]: { + // attempts: [ + // {timestamp: 1529598899017}, + // ... + // ] + // }, + // ... + // } + failHistory = {}; + + // If true, the failHistory var was updated and needs to be written to disk + needWrite = false; + writeQueue = Promise.resolve(); + + static get () { + if (!ExpoRetry.instance) { + ExpoRetry.instance = new ExpoRetry(); + } + + return ExpoRetry.instance; + } + + _getFilePath () { + return path.join(getHashFetchPath(), 'fail_history.json'); + } + + _getKey (hash, url) { + return `${hash}:${url}`; + } + + load () { + const filePath = this._getFilePath(); + + return fsExists(filePath) + .then(() => + fsReadJson(filePath) + .catch(e => { + throw new Error(`Couldn't parse JSON for ExpoRetry file ${filePath} ${e}`); + }) + ) + .then(failHistory => { + this.failHistory = failHistory; + }) + .catch(() => fsWriteJson(filePath, this.failHistory)); + } + + canAttemptDownload (hash, url) { + const key = this._getKey(hash, url); + + // Never tried downloading the file + if (!(key in this.failHistory) || !this.failHistory[key].attempts.length) { + return true; + } + + // Already failed at downloading the file: check if we can retry now + // Delay starts at 30 seconds, max delay is 23 days + const retriesCount = this.failHistory[key].attempts.length - 1; + const latestAttemptTimestamp = this.failHistory[key].attempts.slice(-1)[0].timestamp; + const earliestNextAttemptTimestamp = latestAttemptTimestamp + Math.pow(2, Math.min(16, retriesCount)) * 30000; + + if (Date.now() > earliestNextAttemptTimestamp) { + return true; + } + + return false; + } + + registerFailedAttempt (hash, url) { + const key = this._getKey(hash, url); + + this.failHistory[key] = this.failHistory[key] || { attempts: [] }; + this.failHistory[key].attempts.push({ timestamp: Date.now() }); + + // Once the ongoing write is finished, write anew with the updated contents + this.needWrite = true; + this.writeQueue = this.writeQueue.then(() => { + if (this.needWrite) { + // Skip subsequent promises, considering we are writing the latest value + this.needWrite = false; + + return fsWriteJson(this._getFilePath(), this.failHistory); + } + }); + } +} diff --git a/src/util/hashFetch/index.js b/src/util/hashFetch/index.js new file mode 100644 index 000000000..6ade65428 --- /dev/null +++ b/src/util/hashFetch/index.js @@ -0,0 +1,247 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +const fs = window.require('fs'); +const util = window.require('util'); +const path = window.require('path'); + +import unzip from 'unzipper'; + +import { getHashFetchPath } from '../host'; +import ExpoRetry from './expoRetry'; +import Contracts from '@parity/shared/lib/contracts'; +import { sha3 } from '@parity/api/lib/util/sha3'; +import { bytesToHex } from '@parity/api/lib/util/format'; +import { ensureDir as fsEnsureDir, emptyDir as fsEmptyDir } from 'fs-extra'; +import { http, https } from 'follow-redirects'; + +const fsExists = util.promisify(fs.stat); +const fsStat = util.promisify(fs.stat); +const fsRename = util.promisify(fs.rename); +const fsReadFile = util.promisify(fs.readFile); +const fsUnlink = util.promisify(fs.unlink); +const fsReaddir = util.promisify(fs.readdir); +const fsRmdir = util.promisify(fs.rmdir); + +const MAX_DOWNLOADED_FILE_SIZE_BYTES = 10485760; // 20MB + +function registerFailedAttemptAndThrow (hash, url, e) { + ExpoRetry.get().registerFailedAttempt(hash, url); + throw e; +} + +function checkHashMatch (hash, path) { + return fsReadFile(path).then(content => { + if (sha3(content) !== `0x${hash}`) { throw new Error(`Hashes don't match: expected 0x${hash}, got ${sha3(content)}`); } + }); +} + +// List directory contents and tell if each item is a file or a directory +function ls (folderPath) { + return fsReaddir(folderPath) + .then(filenames => + Promise.all(filenames.map(filename => { + const filePath = path.join(folderPath, filename); + + return fsStat(filePath).then(stat => ({ isDirectory: stat.isDirectory(), filePath, filename })); + })) + ); +} + +function rawUnzipTo (zipPath, extractPath) { + return new Promise((resolve, reject) => { + const unzipParser = unzip.Extract({ path: extractPath }); + + fs.createReadStream(zipPath).pipe(unzipParser); + + unzipParser.on('error', reject); + + unzipParser.on('close', resolve); + }); +} + +function unzipThroughTo (tempPath, extractPath, finalPath) { + return rawUnzipTo(tempPath, extractPath) + .then(() => fsUnlink(tempPath)) + .then(() => ls(extractPath)) + .then(files => { + // Check if the zip file contained a root folder + if (files.length === 1 && files[0].isDirectory) { + // Rename the root folder (contaning the dapp) to finalPath + const rootFolderPath = files[0].filePath; + + return fsRename(rootFolderPath, finalPath) + .then(() => fsRmdir(extractPath)); + } else { + // No root folder: extractPath contains the dapp + return fsRename(extractPath, finalPath); + } + }); +} + +function download (url, destinationPath) { + const file = fs.createWriteStream(destinationPath); // Will replace any existing file + + return new Promise((resolve, reject) => { + const httpx = url.startsWith('https:') ? https : http; + + httpx.get(url, response => { + var size = 0; + + response.on('data', (data) => { + size += data.length; + + if (size > MAX_DOWNLOADED_FILE_SIZE_BYTES) { + response.destroy(); + response.unpipe(file); + fsUnlink(destinationPath); + reject(`File download aborted: exceeded maximum size of ${MAX_DOWNLOADED_FILE_SIZE_BYTES} bytes`); + } + }); + + response.pipe(file); + + file.on('finish', () => { + file.close(resolve); + }); + }); + }); +} + +function hashDownload (hash, url, zip = false) { + const tempFilename = `${hash}.part`; + const tempPath = path.join(getHashFetchPath(), 'partial', tempFilename); + + const finalPath = path.join(getHashFetchPath(), 'files', hash); + + return download(url, tempPath) + // Don't register a failed attempt if the download failed; the user might be offline. + .then(() => checkHashMatch(hash, tempPath).catch(e => registerFailedAttemptAndThrow(hash, url, e))) + .then(() => { // Hashes match + if (!zip) { + return fsRename(tempPath, finalPath); + } else { + const extractPath = path.join(getHashFetchPath(), 'partial-extract', tempFilename); + + return unzipThroughTo(tempPath, extractPath, finalPath); + } + }); +} + +function queryRegistryAndDownload (api, hash, expected) { + const { githubHint } = Contracts.get(api); + + return githubHint.getEntry(`0x${hash}`).then(([slug, commitBytes, author]) => { + const commit = bytesToHex(commitBytes); + + if (!slug) { + if (commit === '0x0000000000000000000000000000000000000000' && author === '0x0000000000000000000000000000000000000000') { + throw new Error(`No GitHub Hint entry found.`); + } else { + throw new Error(`GitHub Hint entry has empty slug.`); + } + } + + let url; + let zip; + + if (commit === '0x0000000000000000000000000000000000000000') { // The slug is the URL to a file + if (!slug.toLowerCase().startsWith('http')) { throw new Error(`GitHub Hint URL ${slug} isn't HTTP/HTTPS.`); } + url = slug; + zip = false; + } else if (commit === '0x0000000000000000000000000000000000000001') { // The slug is the URL to a dapp zip file + if (!slug.toLowerCase().startsWith('http')) { throw new Error(`GitHub Hint URL ${slug} isn't HTTP/HTTPS.`); } + url = slug; + zip = true; + } else { // The slug is the `owner/repo` of a dapp stored in GitHub + url = `https://codeload.github.com/${slug}/zip/${commit.substr(2)}`; + zip = true; + } + + if (ExpoRetry.get().canAttemptDownload(hash, url) === false) { + throw new Error(`Previous attempt at downloading ${hash} from ${url} failed; retry delay time not yet elapsed.`); + } + + return hashDownload(hash, url, zip); + }); +} + +function checkExpectedMatch (hash, filePath, expected) { + return fsStat(filePath).then(stat => { + if (stat.isDirectory() && expected === 'file') { + throw new Error(`Expected ${hash} to be a file; got a folder (dapp).`); + } else if (!stat.isDirectory() && expected === 'dapp') { + throw new Error(`Expected ${hash} to be a dapp; got a file.`); + } + }); +} + +// Download a file or download and extract a dapp zip archive, using GitHub Hint +// and the content hash of the file +export default class HashFetch { + static instance = null; + initialize = null; // Initialization promise + promises = {}; // Unsettled or resolved HashFetch#fetch promises only + + static get () { + if (!HashFetch.instance) { + HashFetch.instance = new HashFetch(); + } + + return HashFetch.instance; + } + + constructor () { + this.initialize = this._initialize(); + } + + _initialize () { + const hashFetchPath = getHashFetchPath(); + + return fsEnsureDir(hashFetchPath) + .then(() => + Promise.all([ + fsEnsureDir(path.join(hashFetchPath, 'files')), + fsEmptyDir(path.join(hashFetchPath, 'partial')), + fsEmptyDir(path.join(hashFetchPath, 'partial-extract')), + ExpoRetry.get().load() + ])) + .catch(e => { + throw new Error(`HashFetch initialization failed ${e}`); + }); + } + + // Returns a Promise that resolves with the path to the file or directory. + // `expected` is either 'file' or 'dapp'. + fetch (api, hash, expected) { + hash = hash.toLowerCase(); + + if (!/^[0-9a-z]{64}$/.test(hash)) { return Promise.reject(`${hash} isn't a valid hash.`); } + + return this.initialize.then(() => { + const filePath = path.join(getHashFetchPath(), 'files', hash); + + if (!(hash in this.promises)) { // There is no ongoing or resolved fetch for this hash + this.promises[hash] = fsExists(filePath) + .catch(() => queryRegistryAndDownload(api, hash, expected)) + .then(() => checkExpectedMatch(hash, filePath, expected)) + .then(() => filePath) + .catch(e => { delete this.promises[hash]; throw e; }); // Don't prevent retries if the fetch failed + } + return this.promises[hash]; + }); + } +} diff --git a/src/util/host.js b/src/util/host.js index b6accd5d2..57423d330 100644 --- a/src/util/host.js +++ b/src/util/host.js @@ -62,11 +62,20 @@ export function getBuildPath () { return buildPath; } +export function getHashFetchPath () { + // Condition necessary for store.spec.js + const userData = isElectron() + ? window.require('electron').remote.app.getPath('userData') + : path.join(__dirname, 'userData'); + + return path.join(userData, 'hashfetch'); +} + export function getLocalDappsPath () { // Condition necessary for store.spec.js const userData = isElectron() ? window.require('electron').remote.app.getPath('userData') - : path.join(__dirname, 'dapps'); + : path.join(__dirname, 'userData'); return path.join(userData, 'dapps'); } diff --git a/webpack/app.js b/webpack/app.js index 3b51e6f4c..1d055194d 100644 --- a/webpack/app.js +++ b/webpack/app.js @@ -157,9 +157,7 @@ module.exports = { unsafeCache: true }, - node: { - fs: 'empty' - }, + target: 'electron-renderer', plugins: (function () { let plugins = Shared.getPlugins().concat( From ecb4e93d6032f0fe4e55f3e8a865bf1f5f2b3860 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Thu, 21 Jun 2018 19:45:00 +0200 Subject: [PATCH 02/14] Remove obsolete Rust files --- Cargo.precompiled.toml | 19 ---- Cargo.toml | 18 ---- build.rs | 22 ----- src/DappRequests/methodGroups.js | 2 - src/lib.rs | 22 ----- src/lib.rs.in | 55 ----------- src/secureApi.js | 52 +---------- wasm/README.md | 3 - wasm/ethkey/.gitignore | 2 - wasm/ethkey/Cargo.toml | 17 ---- wasm/ethkey/base64ify.js | 5 - wasm/ethkey/build.sh | 16 ---- wasm/ethkey/ethkey.opt.wasm | Bin 55961 -> 0 bytes wasm/ethkey/ethkey.wasm | Bin 67263 -> 0 bytes wasm/ethkey/src/main.rs | 153 ------------------------------- 15 files changed, 1 insertion(+), 385 deletions(-) delete mode 100644 Cargo.precompiled.toml delete mode 100644 Cargo.toml delete mode 100644 build.rs delete mode 100644 src/lib.rs delete mode 100644 src/lib.rs.in delete mode 100644 wasm/README.md delete mode 100644 wasm/ethkey/.gitignore delete mode 100644 wasm/ethkey/Cargo.toml delete mode 100644 wasm/ethkey/base64ify.js delete mode 100755 wasm/ethkey/build.sh delete mode 100644 wasm/ethkey/ethkey.opt.wasm delete mode 100644 wasm/ethkey/ethkey.wasm delete mode 100644 wasm/ethkey/src/main.rs diff --git a/Cargo.precompiled.toml b/Cargo.precompiled.toml deleted file mode 100644 index d627a2c38..000000000 --- a/Cargo.precompiled.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -description = "Parity built-in dapps." -name = "parity-ui-precompiled" -version = "1.9.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -build = "build.rs" - -[features] -default = ["with-syntex", "use-precompiled-js"] -use-precompiled-js = ["parity-dapps-glue/use-precompiled-js"] -with-syntex = ["parity-dapps-glue/with-syntex"] - -[build-dependencies] -parity-dapps-glue = "1.9" - -[dependencies] -parity-dapps-glue = "1.9" - diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 440f2f2fb..000000000 --- a/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -description = "Parity built-in dapps." -name = "parity-ui-dev" -version = "1.9.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -build = "build.rs" - -[features] -default = ["with-syntex"] -with-syntex = ["parity-dapps-glue/with-syntex"] - -[build-dependencies] -parity-dapps-glue = "1.9" - -[dependencies] -parity-dapps-glue = "1.9" - diff --git a/build.rs b/build.rs deleted file mode 100644 index a9a5ba8a6..000000000 --- a/build.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -extern crate parity_dapps_glue; - -fn main() { - parity_dapps_glue::js::build(env!("CARGO_MANIFEST_DIR"), "build"); - parity_dapps_glue::generate(); -} diff --git a/src/DappRequests/methodGroups.js b/src/DappRequests/methodGroups.js index efcf6a227..68c1a01bb 100644 --- a/src/DappRequests/methodGroups.js +++ b/src/DappRequests/methodGroups.js @@ -22,8 +22,6 @@ const methodGroups = { }, dapps: { methods: [ - 'parity_dappsRefresh', - 'parity_dappsUrl', 'shell_getApps', 'shell_getMethodPermissions' ] diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 04efa7cc5..000000000 --- a/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -#[cfg(feature = "with-syntex")] -include!(concat!(env!("OUT_DIR"), "/lib.rs")); - -#[cfg(not(feature = "with-syntex"))] -include!("lib.rs.in"); - diff --git a/src/lib.rs.in b/src/lib.rs.in deleted file mode 100644 index b811c1066..000000000 --- a/src/lib.rs.in +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -extern crate parity_dapps_glue; - -use std::collections::HashMap; -use parity_dapps_glue::{WebApp, File, Info}; - -#[derive(WebAppFiles)] -#[webapp(path = "../build")] -pub struct App { - pub files: HashMap<&'static str, File>, -} - -impl Default for App { - fn default() -> App { - App { - files: Self::files(), - } - } -} - -impl WebApp for App { - fn file(&self, path: &str) -> Option<&File> { - self.files.get(path) - } - - fn info(&self) -> Info { - Info { - name: "Parity UI", - version: env!("CARGO_PKG_VERSION"), - author: "Parity ", - description: "New UI for Parity.", - icon_url: "icon.png", - } - } -} - -#[test] -fn test_js() { - parity_dapps_glue::js::build(env!("CARGO_MANIFEST_DIR"), "build"); -} diff --git a/src/secureApi.js b/src/secureApi.js index d9b20883b..2b20ddee8 100644 --- a/src/secureApi.js +++ b/src/secureApi.js @@ -29,7 +29,6 @@ export default class SecureApi extends Api { _needsToken = false; _tokens = []; - _dappsUrl = null; _wsUrl = null; static getWsProvider (url, protocol, sysuiToken) { @@ -73,44 +72,7 @@ export default class SecureApi extends Api { wsProvider.on('close', this.connect, this); this - .connect() // Connect with token - .then(() => this._fetchSettings()); // Update this._dappsUrl - } - - get _dappsAddress () { - if (!this._dappsUrl) { - return { - host: null, - port: 8545 - }; - } - - const [host, port] = this._dappsUrl.split(':'); - - return { - host, - port: port ? parseInt(port, 10) : null - }; - } - - get dappsPort () { - return this._dappsAddress.port; - } - - get dappsUrl () { - const { port } = this._dappsAddress; - - return port - ? `${this.protocol()}//${this.hostname}:${port}` - : `${this.protocol()}//${this.hostname}`; - } - - get hostname () { - if (window.location.hostname === 'home.parity') { - return 'dapps.parity'; - } - - return this._dappsAddress.host || '127.0.0.1'; + .connect(); // Connect with token } get isConnecting () { @@ -322,18 +284,6 @@ export default class SecureApi extends Api { }); } - /** - * Retrieve the correct ports from the Node - */ - _fetchSettings () { - return this.parity - .dappsUrl() - .catch(() => null) - .then((dappsUrl) => { - this._dappsUrl = this._resolveHost(dappsUrl); - }); - } - /** * Try to generate an Authorization Token. * Then try to connect with the new token. diff --git a/wasm/README.md b/wasm/README.md deleted file mode 100644 index 46a01b180..000000000 --- a/wasm/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# WASM modules - -- `ethkey` -> `/js/packages/api/local/ethkey/ethkey.wasm` diff --git a/wasm/ethkey/.gitignore b/wasm/ethkey/.gitignore deleted file mode 100644 index a9d37c560..000000000 --- a/wasm/ethkey/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target -Cargo.lock diff --git a/wasm/ethkey/Cargo.toml b/wasm/ethkey/Cargo.toml deleted file mode 100644 index 22e5bf553..000000000 --- a/wasm/ethkey/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -description = "Parity ethkey WASM module." -name = "parity-ethkey-wasm" -version = "1.9.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] - -[workspace] -members = [] - -[dependencies] -tiny-keccak = "1.3" -tiny-secp256k1 = "0.1" -libc = { version = "0.2.14", default-features = false } - -[profile.release] -panic = "abort" diff --git a/wasm/ethkey/base64ify.js b/wasm/ethkey/base64ify.js deleted file mode 100644 index 853d05257..000000000 --- a/wasm/ethkey/base64ify.js +++ /dev/null @@ -1,5 +0,0 @@ -const fs = require('fs'); - -const file = fs.readFileSync('./ethkey.opt.wasm', { encoding: 'base64' }); - -fs.writeFileSync('../../packages/api/local/ethkey/ethkey.wasm.js', `module.exports = new Buffer('${file}', 'base64');\n`); diff --git a/wasm/ethkey/build.sh b/wasm/ethkey/build.sh deleted file mode 100755 index 5a3035eba..000000000 --- a/wasm/ethkey/build.sh +++ /dev/null @@ -1,16 +0,0 @@ -# Remove previous build to avoid name conflicts -rm -rf target/wasm32-unknown-emscripten/* - -# Build using nightly rustc + emscripten -rustup run nightly cargo build --release --target=wasm32-unknown-emscripten - -# Copy final WASM file over -cp ./target/wasm32-unknown-emscripten/release/deps/parity_ethkey_wasm-*.wasm ./ethkey.wasm - -# Create a Base64-encoded JS version of the wasm file for easy inclusion in Webpack -node base64ify - -# Copy Base64-encoded JS version to src -cp ./ethkey.wasm.js ../../packages/api/local/ethkey/ethkey.wasm.js - -# rm -f ./ethkey.wasm ./ethkey.opt.wasm ./ethkey.wasm.js diff --git a/wasm/ethkey/ethkey.opt.wasm b/wasm/ethkey/ethkey.opt.wasm deleted file mode 100644 index 1cbbd4a65057007d6985a68c642482d766c96089..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55961 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 diff --git a/wasm/ethkey/src/main.rs b/wasm/ethkey/src/main.rs deleted file mode 100644 index 01ecd0b40..000000000 --- a/wasm/ethkey/src/main.rs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -#![feature(lang_items, core_intrinsics)] -#![feature(start)] -#![feature(link_args)] -#![no_std] -use core::intrinsics; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; -extern crate tiny_keccak; -extern crate tiny_secp256k1; - -use tiny_secp256k1::{is_valid_secret, create_public_key, ECPointG}; - -// #[link_args = "-s EXPORTED_FUNCTIONS=['_input_ptr','_secret_ptr','_public_ptr','_address_ptr','_ecpointg','_verify_secret','_brain']"] -// extern {} - -use tiny_keccak::Keccak; - -pub trait Keccak256 { - fn keccak256(&self) -> T; -} - -impl Keccak256<[u8; 32]> for [u8] { - #[inline] - fn keccak256(&self) -> [u8; 32] { - let mut keccak = Keccak::new_keccak256(); - let mut result = [0u8; 32]; - keccak.update(self); - keccak.finalize(&mut result); - result - } -} - -static mut INPUT: [u8; 1024] = [0; 1024]; -static mut SECRET: [u8; 32] = [0; 32]; -static mut PUBLIC: [u8; 64] = [0; 64]; -static mut ADDRESS: [u8; 20] = [0; 20]; -static mut G: Option = None; - -#[no_mangle] -pub extern "C" fn ecpointg() -> &'static ECPointG { - let g = unsafe { &G }; - - if let Some(ref g) = *g { - return g; - } - - unsafe { G = Some(ECPointG::new()) }; - g.as_ref().expect("value set above; qed") -} - -#[no_mangle] -pub extern "C" fn input_ptr() -> *const u8 { - unsafe { INPUT.as_ptr() } -} - -#[no_mangle] -pub extern "C" fn secret_ptr() -> *const u8 { - unsafe { SECRET.as_ptr() } -} - -#[no_mangle] -pub extern "C" fn public_ptr() -> *const u8 { - unsafe { PUBLIC.as_ptr() } -} - -#[no_mangle] -pub extern "C" fn address_ptr() -> *const u8 { - unsafe { ADDRESS.as_ptr() } -} - -#[no_mangle] -pub extern "C" fn verify_secret() -> bool { - is_valid_secret(unsafe { &SECRET }) -} - -#[no_mangle] -pub extern "C" fn brain(input_len: usize) { - let data = unsafe { &INPUT[..input_len] }; - let mut secret_out = unsafe { &mut SECRET }; - let mut public_out = unsafe { &mut PUBLIC }; - let mut address_out = unsafe { &mut ADDRESS }; - - let g = ecpointg(); - let mut secret = data.keccak256(); - - let mut i = 0; - loop { - secret = secret.keccak256(); - - match i > 16384 { - false => i += 1, - true => { - if let Some(public) = create_public_key(g, &secret) { - let public = &public[1..]; - let hash = public.keccak256(); - - address_out.copy_from_slice(&hash[12..]); - - if address_out[0] == 0 { - public_out.copy_from_slice(&public); - secret_out.copy_from_slice(&secret); - return; - } - } - } - } - } -} - -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -// This function may be needed based on the compilation target. -#[lang = "eh_unwind_resume"] -#[no_mangle] -pub extern fn rust_eh_unwind_resume() { -} - -#[lang = "panic_fmt"] -#[no_mangle] -pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, - _file: &'static str, - _line: u32) -> ! { - unsafe { intrinsics::abort() } -} From 5ef03f379b6b26ff6c4a1108ecde606bb9b9b59f Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Thu, 21 Jun 2018 19:56:37 +0200 Subject: [PATCH 03/14] package-lock.json --- package-lock.json | 516 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 414 insertions(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index d5be6adc2..586127ba4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -505,6 +505,50 @@ "yargs": "6.6.0" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, "mobx": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/mobx/-/mobx-2.6.4.tgz", @@ -520,6 +564,26 @@ "hoist-non-react-statics": "^1.2.0" } }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, "react-redux": { "version": "4.4.6", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-4.4.6.tgz", @@ -531,6 +595,106 @@ "lodash": "^4.2.0", "loose-envify": "^1.1.0" } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "solc": { + "version": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", + "from": "github:ngotchac/solc-js", + "dev": true, + "requires": { + "memorystream": "^0.3.1", + "require-from-string": "^1.1.0", + "yargs": "^4.7.1" + }, + "dependencies": { + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } } } }, @@ -1557,6 +1721,16 @@ "integrity": "sha1-jgOPbdsUvXZa4fS1IW4SCUUR4NA=", "dev": true }, + "solc": { + "version": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", + "from": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", + "dev": true, + "requires": { + "memorystream": "^0.3.1", + "require-from-string": "^1.1.0", + "yargs": "^4.7.1" + } + }, "webrtc-adapter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-2.1.0.tgz", @@ -1594,6 +1768,28 @@ "schema-utils": "^0.3.0" } }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + }, "zxcvbn": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.1.tgz", @@ -1663,9 +1859,9 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" + "fbjs": "^0.8.16", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" } }, "semantic-ui-react": { @@ -1673,11 +1869,11 @@ "resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-0.78.3.tgz", "integrity": "sha512-JRmuqjyigCehHfzrS2ir5nGoytZWCifU8G2T++G/CMdahUJBME7S6E9rU7WW9Qg2Fqn2aJIxfn6Ry/rlOTJDOw==", "requires": { - "babel-runtime": "6.26.0", - "classnames": "2.2.5", - "fbjs": "0.8.16", - "lodash": "4.17.10", - "prop-types": "15.6.1" + "babel-runtime": "^6.25.0", + "classnames": "^2.2.5", + "fbjs": "^0.8.16", + "lodash": "^4.17.4", + "prop-types": "^15.5.10" } } } @@ -1791,7 +1987,7 @@ "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-4.0.3.tgz", "integrity": "sha1-QOsx0l4LjWMEjtojdsxWv6vRT3U=", "requires": { - "hoist-non-react-statics": "1.2.0" + "hoist-non-react-statics": "^1.2.0" } }, "react-redux": { @@ -1799,10 +1995,10 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-4.4.6.tgz", "integrity": "sha1-S50ymFMHoRCWot1hVhmABE/MYgk=", "requires": { - "hoist-non-react-statics": "1.2.0", - "invariant": "2.2.2", - "lodash": "4.17.4", - "loose-envify": "1.3.1" + "hoist-non-react-statics": "^1.0.3", + "invariant": "^2.0.0", + "lodash": "^4.2.0", + "loose-envify": "^1.1.0" } }, "redux": { @@ -1810,10 +2006,10 @@ "resolved": "https://registry.npmjs.org/redux/-/redux-3.6.0.tgz", "integrity": "sha1-iHwrPQub2G7KK+cFccJ2VMGeGI0=", "requires": { - "lodash": "4.17.4", - "lodash-es": "4.17.4", - "loose-envify": "1.3.1", - "symbol-observable": "1.1.0" + "lodash": "^4.2.1", + "lodash-es": "^4.2.1", + "loose-envify": "^1.1.0", + "symbol-observable": "^1.0.2" } } } @@ -1919,10 +2115,10 @@ "resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-0.76.0.tgz", "integrity": "sha512-CdiIT8n7ZwUlytZkYsQMnaVGmoIZI/mVs4lijvLcR568kcnlRkYYaFKhMLq5tFDQU6+QhdTD+8WebF7ov0Ql6Q==", "requires": { - "babel-runtime": "6.26.0", - "classnames": "2.2.5", - "lodash": "4.17.4", - "prop-types": "15.5.10" + "babel-runtime": "^6.25.0", + "classnames": "^2.2.5", + "lodash": "^4.17.4", + "prop-types": "^15.5.10" } }, "store": { @@ -2856,7 +3052,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } } } @@ -3814,8 +4010,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base32.js": { "version": "0.1.0", @@ -3857,6 +4052,11 @@ "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, + "big-integer": { + "version": "1.6.31", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.31.tgz", + "integrity": "sha512-lDbZNHHwxDKnjP7LWg2leO+tjs4SyVs2Z83dsR1Idbe2urRnxZAUdeQ8YBhHaGaWK/4WM3mz+RlbZsgqck17CA==" + }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", @@ -3868,6 +4068,15 @@ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.0.1.tgz", "integrity": "sha1-gHZS0Q453jfp40lyR+3HmLt0b3Y=" }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", @@ -4067,7 +4276,6 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4257,6 +4465,16 @@ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", "dev": true }, + "buffer-indexof-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz", + "integrity": "sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8=" + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, "buffer-to-vinyl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", @@ -4282,6 +4500,11 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" + }, "builder-util": { "version": "5.7.9", "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-5.7.9.tgz", @@ -4603,6 +4826,21 @@ "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.0.tgz", "integrity": "sha1-DUqzfn4Y6tC9xHuSB2QRjOWHM9w=" }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "requires": { + "traverse": ">=0.3.0 <0.4" + }, + "dependencies": { + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" + } + } + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -5080,8 +5318,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "1.6.0", @@ -7096,7 +7333,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, "requires": { "readable-stream": "^2.0.2" } @@ -7294,15 +7530,15 @@ "integrity": "sha512-SQYDGMLpTgty1bx3NycuDb7dNPzktVSdK2sqPZjyRocauq/uN/V4S2lcpFVLupaHhKlD8zozm9fTpm5UdohvTg==", "dev": true, "requires": { - "debug": "3.1.0", - "env-paths": "1.0.0", - "fs-extra": "4.0.3", - "minimist": "1.2.0", - "nugget": "2.0.1", - "path-exists": "3.0.0", - "rc": "1.2.2", - "semver": "5.4.1", - "sumchecker": "2.0.2" + "debug": "^3.0.0", + "env-paths": "^1.0.0", + "fs-extra": "^4.0.1", + "minimist": "^1.2.0", + "nugget": "^2.0.1", + "path-exists": "^3.0.0", + "rc": "^1.2.1", + "semver": "^5.4.1", + "sumchecker": "^2.0.2" } }, "find-up": { @@ -7311,7 +7547,7 @@ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "fs-extra": { @@ -7320,9 +7556,9 @@ "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, "has-flag": { @@ -7343,7 +7579,7 @@ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" } }, "minimist": { @@ -7358,9 +7594,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "path-exists": { @@ -7375,8 +7611,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -7385,7 +7621,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "sumchecker": { @@ -7394,7 +7630,7 @@ "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", "dev": true, "requires": { - "debug": "2.6.9" + "debug": "^2.2.0" }, "dependencies": { "debug": { @@ -7447,18 +7683,18 @@ "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", "dev": true, "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" } }, "yargs-parser": { @@ -7467,7 +7703,7 @@ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } } } @@ -8556,7 +8792,7 @@ "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { - "find-up": "1.1.2" + "find-up": "^1.0.0" } } } @@ -9942,9 +10178,9 @@ "dev": true }, "follow-redirects": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", - "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", + "integrity": "sha512-fdrt472/9qQ6Kgjvb935ig6vJCuofpBUD14f9Vb+SLlm7xIe4Qva5gey8EKtv8lp7ahE1wilg3xL1znpVGtZIA==", "requires": { "debug": "^3.1.0" }, @@ -10039,13 +10275,12 @@ "dev": true }, "fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", - "dev": true, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", "requires": { "graceful-fs": "^4.1.2", - "jsonfile": "^3.0.0", + "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, @@ -10090,8 +10325,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.1.2", @@ -10197,6 +10431,7 @@ "version": "2.10.1", "bundled": true, "dev": true, + "optional": true, "requires": { "hoek": "2.x.x" } @@ -10213,7 +10448,8 @@ "buffer-shims": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "caseless": { "version": "0.12.0", @@ -10230,12 +10466,14 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "combined-stream": { "version": "1.0.5", "bundled": true, "dev": true, + "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -10248,12 +10486,14 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "cryptiles": { "version": "2.0.5", @@ -10299,7 +10539,8 @@ "delayed-stream": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "delegates": { "version": "1.0.0", @@ -10325,7 +10566,8 @@ "extsprintf": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "forever-agent": { "version": "0.6.1", @@ -10459,7 +10701,8 @@ "hoek": { "version": "2.16.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "http-signature": { "version": "1.1.1", @@ -10496,6 +10739,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10509,7 +10753,8 @@ "isarray": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "isstream": { "version": "0.1.2", @@ -10582,12 +10827,14 @@ "mime-db": { "version": "1.27.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "mime-types": { "version": "2.1.15", "bundled": true, "dev": true, + "optional": true, "requires": { "mime-db": "~1.27.0" } @@ -10661,7 +10908,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "oauth-sign": { "version": "0.8.2", @@ -10719,7 +10967,8 @@ "process-nextick-args": { "version": "1.0.7", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "punycode": { "version": "1.4.1", @@ -10757,6 +11006,7 @@ "version": "2.2.9", "bundled": true, "dev": true, + "optional": true, "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -10866,6 +11116,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -10876,6 +11127,7 @@ "version": "1.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -10959,7 +11211,8 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "uuid": { "version": "3.0.1", @@ -10996,7 +11249,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -11129,7 +11381,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -12191,7 +12442,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -13549,10 +13799,9 @@ "dev": true }, "jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "requires": { "graceful-fs": "^4.1.6" } @@ -13864,6 +14113,11 @@ "immediate": "~3.0.5" } }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=" + }, "load-bmfont": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.3.0.tgz", @@ -14638,7 +14892,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -16931,8 +17184,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -19267,9 +19519,9 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" + "fbjs": "^0.8.16", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" } } } @@ -19712,6 +19964,17 @@ "locate-path": "^2.0.0" } }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -19802,6 +20065,15 @@ "esprima": "^4.0.0" } }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsx-ast-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", @@ -21116,7 +21388,6 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "^7.0.5" } @@ -23958,8 +24229,7 @@ "universalify": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", - "dev": true + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, "unpipe": { "version": "1.0.0", @@ -23988,6 +24258,48 @@ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=" }, + "unzipper": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.8.14.tgz", + "integrity": "sha512-8rFtE7EP5ssOwGpN2dt1Q4njl0N1hUXJ7sSPz0leU2hRdq6+pra57z4YPBlVqm40vcgv6ooKZEAx48fMTv9x4w==", + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "~1.0.10", + "listenercount": "~1.0.1", + "readable-stream": "~2.1.5", + "setimmediate": "~1.0.4" + }, + "dependencies": { + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=" + }, + "readable-stream": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "requires": { + "buffer-shims": "^1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "update-notifier": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.3.0.tgz", @@ -25040,7 +25352,7 @@ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { - "prr": "1.0.1" + "prr": "~1.0.1" } }, "prr": { From cd1a5e9d8d7f220ade5ca8cf9231b14f335bf9ab Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Thu, 21 Jun 2018 20:01:39 +0200 Subject: [PATCH 04/14] Linting --- src/Dapp/dapp.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Dapp/dapp.css b/src/Dapp/dapp.css index 482b31b36..a9cb7dda7 100644 --- a/src/Dapp/dapp.css +++ b/src/Dapp/dapp.css @@ -29,18 +29,17 @@ .full { font-family: 'Roboto', sans-serif; - font-size: 16px; + font-size: 2em; font-weight: 300; display: flex; align-items: center; justify-content: center; - font-size: 2em; color: #999; } .loading { opacity: 0; - animation-duration: .5s; + animation-duration: 0.5s; animation-name: fadeIn; animation-delay: 1.5s; animation-fill-mode: forwards; @@ -50,6 +49,7 @@ from { opacity: 0; } + to { opacity: 1; } From 8452e2fa956648b193ca3dbe9e66a057b5ada23f Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Sun, 24 Jun 2018 17:23:30 +0200 Subject: [PATCH 05/14] Fix tests --- .gitignore | 1 + package-lock.json | 56 ++++++++------------------------- src/Connection/connection.js | 2 +- src/index.parity.js | 2 +- src/util/dapps.js | 4 +-- src/util/hashFetch/expoRetry.js | 6 ++-- src/util/hashFetch/index.js | 6 ++-- src/util/host.js | 10 +++--- 8 files changed, 29 insertions(+), 58 deletions(-) diff --git a/.gitignore b/.gitignore index 242dea65d..d1fa2159a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ npm-debug.log build dist docs +test/tmp .build .coverage .dist diff --git a/package-lock.json b/package-lock.json index 586127ba4..dd73672d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -500,7 +500,6 @@ "redux-actions": "1.1.0", "redux-thunk": "2.1.0", "scryptsy": "2.0.0", - "solc": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", "useragent.js": "^0.5.6", "yargs": "6.6.0" }, @@ -508,20 +507,17 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -531,7 +527,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "^1.0.0" } @@ -540,7 +535,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -568,7 +562,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, "requires": { "lcid": "^1.0.0" } @@ -577,7 +570,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", @@ -600,7 +592,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -611,7 +602,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" @@ -619,8 +609,7 @@ }, "solc": { "version": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", - "from": "github:ngotchac/solc-js", - "dev": true, + "from": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", "requires": { "memorystream": "^0.3.1", "require-from-string": "^1.1.0", @@ -631,7 +620,6 @@ "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "dev": true, "requires": { "cliui": "^3.2.0", "decamelize": "^1.1.1", @@ -655,7 +643,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -666,7 +653,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -675,7 +661,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, "requires": { "is-utf8": "^0.2.0" } @@ -683,14 +668,12 @@ "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, "yargs-parser": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, "requires": { "camelcase": "^3.0.0", "lodash.assign": "^4.0.6" @@ -10448,8 +10431,7 @@ "buffer-shims": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "caseless": { "version": "0.12.0", @@ -10466,8 +10448,7 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "combined-stream": { "version": "1.0.5", @@ -10486,14 +10467,12 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "cryptiles": { "version": "2.0.5", @@ -10566,8 +10545,7 @@ "extsprintf": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "forever-agent": { "version": "0.6.1", @@ -10701,8 +10679,7 @@ "hoek": { "version": "2.16.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "http-signature": { "version": "1.1.1", @@ -10739,7 +10716,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10753,8 +10729,7 @@ "isarray": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "isstream": { "version": "0.1.2", @@ -10967,8 +10942,7 @@ "process-nextick-args": { "version": "1.0.7", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "punycode": { "version": "1.4.1", @@ -11006,7 +10980,6 @@ "version": "2.2.9", "bundled": true, "dev": true, - "optional": true, "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -11116,7 +11089,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -11127,7 +11099,6 @@ "version": "1.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -11211,8 +11182,7 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "uuid": { "version": "3.0.1", diff --git a/src/Connection/connection.js b/src/Connection/connection.js index 563065c40..05b81b314 100644 --- a/src/Connection/connection.js +++ b/src/Connection/connection.js @@ -33,7 +33,7 @@ import styles from './connection.css'; let electron; if (isElectron()) { - electron = window.require('electron'); + electron = require('electron'); } @observer diff --git a/src/index.parity.js b/src/index.parity.js index c3f96a4c9..73bd0b5e5 100644 --- a/src/index.parity.js +++ b/src/index.parity.js @@ -60,7 +60,7 @@ function renderUI (token) { if (isElectron()) { // Take --flag options from electron if available - const { remote } = window.require('electron'); + const { remote } = require('electron'); wsUrl = `${remote.getGlobal('wsInterface') || '127.0.0.1'}:${remote.getGlobal('wsPort') || '8546'}`; } diff --git a/src/util/dapps.js b/src/util/dapps.js index 2f549b86b..cc44735dc 100644 --- a/src/util/dapps.js +++ b/src/util/dapps.js @@ -27,11 +27,11 @@ import Contracts from '@parity/shared/lib/contracts'; import path from 'path'; -const util = isElectron() ? window.require('util') : require('util'); +const util = require('util'); require('util.promisify').shim(); -const fs = isElectron() ? window.require('fs') : require('fs'); +const fs = require('fs'); const fsReadFile = util.promisify(fs.readFile); const fsReaddir = util.promisify(fs.readdir); const fsStat = util.promisify(fs.stat); diff --git a/src/util/hashFetch/expoRetry.js b/src/util/hashFetch/expoRetry.js index 64133fecd..34d9146af 100644 --- a/src/util/hashFetch/expoRetry.js +++ b/src/util/hashFetch/expoRetry.js @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -const fs = window.require('fs'); -const util = window.require('util'); -const path = window.require('path'); +const fs = require('fs'); +const util = require('util'); +const path = require('path'); import { readJson as fsReadJson, writeJson as fsWriteJson } from 'fs-extra'; const fsExists = util.promisify(fs.stat); diff --git a/src/util/hashFetch/index.js b/src/util/hashFetch/index.js index 6ade65428..d1f606ee0 100644 --- a/src/util/hashFetch/index.js +++ b/src/util/hashFetch/index.js @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -const fs = window.require('fs'); -const util = window.require('util'); -const path = window.require('path'); +const fs = require('fs'); +const util = require('util'); +const path = require('path'); import unzip from 'unzipper'; diff --git a/src/util/host.js b/src/util/host.js index 57423d330..bab0e1e5e 100644 --- a/src/util/host.js +++ b/src/util/host.js @@ -45,7 +45,7 @@ export function redirectLocalhost (token) { export function getBuildPath () { // Condition necessary for store.spec.js const basePath = isElectron() - ? window.require('electron').remote.getGlobal('dirName') + ? require('electron').remote.getGlobal('dirName') : path.join(__dirname, '..'); // Replace all backslashes by front-slashes (happens in Windows) @@ -65,8 +65,8 @@ export function getBuildPath () { export function getHashFetchPath () { // Condition necessary for store.spec.js const userData = isElectron() - ? window.require('electron').remote.app.getPath('userData') - : path.join(__dirname, 'userData'); + ? require('electron').remote.app.getPath('userData') + : path.join(__dirname, '../../test/tmp'); return path.join(userData, 'hashfetch'); } @@ -74,8 +74,8 @@ export function getHashFetchPath () { export function getLocalDappsPath () { // Condition necessary for store.spec.js const userData = isElectron() - ? window.require('electron').remote.app.getPath('userData') - : path.join(__dirname, 'userData'); + ? require('electron').remote.app.getPath('userData') + : path.join(__dirname, '../../test/tmp'); return path.join(userData, 'dapps'); } From a2cc6f07e053fc58cf06eae881f7ba2bc46e5ab9 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Sun, 24 Jun 2018 17:24:10 +0200 Subject: [PATCH 06/14] Lint --- src/util/dapps.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/util/dapps.js b/src/util/dapps.js index cc44735dc..9b7d34d5e 100644 --- a/src/util/dapps.js +++ b/src/util/dapps.js @@ -20,7 +20,6 @@ import { range, uniq } from 'lodash'; import { bytesToHex } from '@parity/api/lib/util/format'; import { getBuildPath, getLocalDappsPath } from './host'; import HashFetch from './hashFetch'; -import isElectron from 'is-electron'; import builtinApps from '../Dapps/dappsBuiltin.json'; import Contracts from '@parity/shared/lib/contracts'; From a76cfef91c6cd6f6d2d050c57ea9298e237d7972 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Sun, 24 Jun 2018 17:31:14 +0200 Subject: [PATCH 07/14] Fix .includes() is not a function (:88) --- electron/operations/runParity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron/operations/runParity.js b/electron/operations/runParity.js index 53aa36aa9..9fec25b44 100644 --- a/electron/operations/runParity.js +++ b/electron/operations/runParity.js @@ -54,7 +54,7 @@ module.exports = { .then(() => fsChmod(parityPath(), '755')) // Should already be 755 after download, just to be sure .then(() => { const logStream = fs.createWriteStream(logFile, { flags: 'a' }); - let logLastLine; // Always contains last line of the logFile + let logLastLine = ''; // Always contains last line of the logFile // Run an instance of parity with the correct args parity = spawn(parityPath(), parityArgv); From 943765dd4c8977301c738fe59dc22380411096e7 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Sun, 24 Jun 2018 17:33:14 +0200 Subject: [PATCH 08/14] Remove rust files from CI build --- scripts/build.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index a6f4a913c..0b6adba78 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -11,11 +11,6 @@ rm -rf $BUILDDIR mkdir -p $BUILDDIR/src BUILD_DEST=$BUILDDIR/build npm run ci:build || EXITCODE=1 -# Copy rust files -cp Cargo.precompiled.toml $BUILDDIR/Cargo.toml -cp build.rs $BUILDDIR -cp src/lib.rs* $BUILDDIR/src - # back to root popd From f76f89cdde20604c68d508788691631bd8a0267b Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Mon, 25 Jun 2018 18:34:48 +0200 Subject: [PATCH 09/14] Update @parity/ui dependency --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd73672d5..295c29a53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1998,9 +1998,9 @@ } }, "@parity/ui": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@parity/ui/-/ui-3.1.7.tgz", - "integrity": "sha512-UqhsKVeaWBkufSwJH8S6HnOaLmQUoDqlu13o9MKfeFtNexcuPk457tRvpMn64Mn6GOLFPJC8Cf9HLD0Bpkpjqg==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@parity/ui/-/ui-3.1.8.tgz", + "integrity": "sha512-izyK7nlzBVBi7sKJiDFJtNOcNzgepEX5x+V9+392+xodPw+lbN4n9zO9Lve8ba2eoywmWbyk3q0ZLsWgsLqSIg==", "requires": { "@parity/api": "~2.1.22", "@parity/etherscan": "2.1.x", @@ -2057,9 +2057,9 @@ } }, "@parity/api": { - "version": "2.1.22", - "resolved": "https://registry.npmjs.org/@parity/api/-/api-2.1.22.tgz", - "integrity": "sha512-I7HfYQakHM1NrZ6LmKQN1BJe81YsnfkjUUv1ZDAbDFVwtgADlmsfchPeX5Cm8flGY2eHd2wlNmBu5+RZtftKxQ==", + "version": "2.1.23", + "resolved": "https://registry.npmjs.org/@parity/api/-/api-2.1.23.tgz", + "integrity": "sha512-Oeo0qvTWczpsMy8IeaN54Jz/JrKLNkIWB69eDE6KsouSnXEOGGh8pWup2LCZoaKhRX3HdXQFYCnWekvsDhst6Q==", "requires": { "@parity/abi": "~2.1.4", "@parity/jsonrpc": "2.1.x", @@ -15024,9 +15024,9 @@ "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=" }, "moment": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", - "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" }, "ms": { "version": "2.0.0", diff --git a/package.json b/package.json index 8f1805e0e..54c3b7e42 100644 --- a/package.json +++ b/package.json @@ -164,7 +164,7 @@ "@parity/plugin-signer-hardware": "github:parity-js/plugin-signer-hardware#e8b8a4e67adc37870e370d22805632d08012b9ee", "@parity/plugin-signer-qr": "github:parity-js/plugin-signer-qr#c275ba13524e9f6759079fabd10faf49cc00cfc0", "@parity/shared": "2.2.28", - "@parity/ui": "3.1.7", + "@parity/ui": "3.1.8", "axios": "0.18.0", "command-exists": "1.2.2", "commander": "2.15.1", From 24f68a7cf4be6bd8bbcd2566a02962f23a39f959 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Tue, 3 Jul 2018 18:45:22 +0200 Subject: [PATCH 10/14] Grumbles --- package-lock.json | 103 ++++++++++++++++++++++++++------ package.json | 1 + src/inject.js | 8 +-- src/util/hashFetch/expoRetry.js | 21 +++---- src/util/hashFetch/index.js | 81 +++++++++++++++++-------- 5 files changed, 153 insertions(+), 61 deletions(-) diff --git a/package-lock.json b/package-lock.json index 295c29a53..32c58ec44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -211,6 +211,13 @@ "bignumber.js": "3.0.1", "js-sha3": "0.5.5", "utf8": "^2.1.2" + }, + "dependencies": { + "js-sha3": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" + } } }, "@parity/api": { @@ -233,6 +240,11 @@ "websocket": "^1.0.25" }, "dependencies": { + "js-sha3": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" + }, "store": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz", @@ -447,6 +459,14 @@ "bignumber.js": "4.1.0", "js-sha3": "0.5.5", "utf8": "^2.1.2" + }, + "dependencies": { + "js-sha3": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=", + "dev": true + } } }, "@parity/api": { @@ -468,6 +488,14 @@ "lodash": "^4.17.4", "store": "^2.0.12", "websocket": "^1.0.25" + }, + "dependencies": { + "js-sha3": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=", + "dev": true + } } }, "@parity/ledger": { @@ -500,6 +528,7 @@ "redux-actions": "1.1.0", "redux-thunk": "2.1.0", "scryptsy": "2.0.0", + "solc": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", "useragent.js": "^0.5.6", "yargs": "6.6.0" }, @@ -507,17 +536,20 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -527,6 +559,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, "requires": { "number-is-nan": "^1.0.0" } @@ -535,6 +568,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -562,6 +596,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, "requires": { "lcid": "^1.0.0" } @@ -570,6 +605,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", @@ -592,6 +628,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -602,6 +639,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" @@ -609,7 +647,8 @@ }, "solc": { "version": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", - "from": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", + "from": "github:ngotchac/solc-js", + "dev": true, "requires": { "memorystream": "^0.3.1", "require-from-string": "^1.1.0", @@ -620,6 +659,7 @@ "version": "4.8.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, "requires": { "cliui": "^3.2.0", "decamelize": "^1.1.1", @@ -643,6 +683,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -653,6 +694,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -661,6 +703,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, "requires": { "is-utf8": "^0.2.0" } @@ -668,12 +711,14 @@ "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true }, "yargs-parser": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true, "requires": { "camelcase": "^3.0.0", "lodash.assign": "^4.0.6" @@ -1385,6 +1430,12 @@ "intl-messageformat": "1.3.0" } }, + "js-sha3": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", + "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=", + "dev": true + }, "keythereum": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/keythereum/-/keythereum-0.4.6.tgz", @@ -10340,7 +10391,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.1.1", @@ -10431,7 +10483,8 @@ "buffer-shims": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "caseless": { "version": "0.12.0", @@ -10448,7 +10501,8 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "combined-stream": { "version": "1.0.5", @@ -10467,12 +10521,14 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "cryptiles": { "version": "2.0.5", @@ -10545,7 +10601,8 @@ "extsprintf": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "forever-agent": { "version": "0.6.1", @@ -10679,7 +10736,8 @@ "hoek": { "version": "2.16.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "http-signature": { "version": "1.1.1", @@ -10716,6 +10774,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10729,7 +10788,8 @@ "isarray": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "isstream": { "version": "0.1.2", @@ -10942,7 +11002,8 @@ "process-nextick-args": { "version": "1.0.7", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "punycode": { "version": "1.4.1", @@ -10980,6 +11041,7 @@ "version": "2.2.9", "bundled": true, "dev": true, + "optional": true, "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -11031,7 +11093,8 @@ "safe-buffer": { "version": "5.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "semver": { "version": "5.3.0", @@ -11089,6 +11152,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -11099,6 +11163,7 @@ "version": "1.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -11113,6 +11178,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -11182,7 +11248,8 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "uuid": { "version": "3.0.1", @@ -13644,9 +13711,9 @@ "dev": true }, "js-sha3": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", - "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.7.0.tgz", + "integrity": "sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA==" }, "js-tokens": { "version": "3.0.2", diff --git a/package.json b/package.json index 54c3b7e42..ed72c7491 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,7 @@ "follow-redirects": "1.5.0", "fs-extra": "6.0.1", "is-electron": "2.1.0", + "js-sha3": "0.7.0", "keythereum": "1.0.2", "lodash.flatten": "4.4.0", "lodash.omitby": "4.6.0", diff --git a/src/inject.js b/src/inject.js index edbce314f..dbfbf07e9 100644 --- a/src/inject.js +++ b/src/inject.js @@ -80,13 +80,11 @@ if (typeof window !== 'undefined' && !window.isParity) { // Disable eval() for dapps // https://electronjs.org/docs/tutorial/security#7-override-and-disable-eval // - // TODO Currently Web3 Console dapp needs eval(), and is the only builtin - // that needs it, so we cannot blindly disable it as per the recommendation. + // TODO Currently Web3 Console dapp needs eval(), so we cannot blindly disable + // it as per the recommendation. // One idea is to check here in inject.js if allowJsEval is set to true, but // this requires more work (future PR). - // For now we simply allow eval(). All builtin dapps are trusted and can use - // eval(), and all network dapps are served on 127.0.0.1:8545, which have CSP - // that disallow eval(). So security-wise it should be enough. + // For now we simply allow eval() for all dapps. // // window.eval = global.eval = function () { // eslint-disable-line // throw new Error(`Sorry, this app does not support window.eval().`); diff --git a/src/util/hashFetch/expoRetry.js b/src/util/hashFetch/expoRetry.js index 34d9146af..7fa453aaa 100644 --- a/src/util/hashFetch/expoRetry.js +++ b/src/util/hashFetch/expoRetry.js @@ -14,12 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -const fs = require('fs'); -const util = require('util'); const path = require('path'); import { readJson as fsReadJson, writeJson as fsWriteJson } from 'fs-extra'; -const fsExists = util.promisify(fs.stat); import { getHashFetchPath } from '../host'; @@ -64,17 +61,11 @@ export default class ExpoRetry { load () { const filePath = this._getFilePath(); - return fsExists(filePath) - .then(() => - fsReadJson(filePath) - .catch(e => { - throw new Error(`Couldn't parse JSON for ExpoRetry file ${filePath} ${e}`); - }) - ) - .then(failHistory => { - this.failHistory = failHistory; - }) - .catch(() => fsWriteJson(filePath, this.failHistory)); + return fsReadJson(filePath) + .then(failHistory => { + this.failHistory = failHistory; + }) + .catch(() => fsWriteJson(filePath, this.failHistory)); } canAttemptDownload (hash, url) { @@ -113,6 +104,8 @@ export default class ExpoRetry { return fsWriteJson(this._getFilePath(), this.failHistory); } + }).catch(() => { + console.error(`Couldn't write to ${this._getFilePath()}`); }); } } diff --git a/src/util/hashFetch/index.js b/src/util/hashFetch/index.js index d1f606ee0..0ed47db36 100644 --- a/src/util/hashFetch/index.js +++ b/src/util/hashFetch/index.js @@ -23,18 +23,13 @@ import unzip from 'unzipper'; import { getHashFetchPath } from '../host'; import ExpoRetry from './expoRetry'; import Contracts from '@parity/shared/lib/contracts'; -import { sha3 } from '@parity/api/lib/util/sha3'; import { bytesToHex } from '@parity/api/lib/util/format'; -import { ensureDir as fsEnsureDir, emptyDir as fsEmptyDir } from 'fs-extra'; +import { ensureDir as fsEnsureDir, emptyDir as fsEmptyDir, move, pathExists, remove } from 'fs-extra'; import { http, https } from 'follow-redirects'; +import { keccak256 } from 'js-sha3'; -const fsExists = util.promisify(fs.stat); const fsStat = util.promisify(fs.stat); -const fsRename = util.promisify(fs.rename); -const fsReadFile = util.promisify(fs.readFile); -const fsUnlink = util.promisify(fs.unlink); const fsReaddir = util.promisify(fs.readdir); -const fsRmdir = util.promisify(fs.rmdir); const MAX_DOWNLOADED_FILE_SIZE_BYTES = 10485760; // 20MB @@ -43,9 +38,24 @@ function registerFailedAttemptAndThrow (hash, url, e) { throw e; } -function checkHashMatch (hash, path) { - return fsReadFile(path).then(content => { - if (sha3(content) !== `0x${hash}`) { throw new Error(`Hashes don't match: expected 0x${hash}, got ${sha3(content)}`); } +function checkHashMatch (expectedHash, path) { + return new Promise((resolve, reject) => { + const hasher = keccak256.create(); + const fileReadStream = fs.createReadStream(path); + + fileReadStream.on('end', () => { + const actualHash = hasher.hex(); + + if (actualHash !== expectedHash) { + reject(`Hashes don't match: expected ${expectedHash}, got ${actualHash}`); + } else { + resolve(); + } + }); + + fileReadStream.on('data', (chunk) => { + hasher.update(chunk); + }); }); } @@ -75,7 +85,7 @@ function rawUnzipTo (zipPath, extractPath) { function unzipThroughTo (tempPath, extractPath, finalPath) { return rawUnzipTo(tempPath, extractPath) - .then(() => fsUnlink(tempPath)) + .then(() => remove(tempPath)) .then(() => ls(extractPath)) .then(files => { // Check if the zip file contained a root folder @@ -83,20 +93,31 @@ function unzipThroughTo (tempPath, extractPath, finalPath) { // Rename the root folder (contaning the dapp) to finalPath const rootFolderPath = files[0].filePath; - return fsRename(rootFolderPath, finalPath) - .then(() => fsRmdir(extractPath)); + return move(rootFolderPath, finalPath) + .then(() => remove(extractPath)); } else { // No root folder: extractPath contains the dapp - return fsRename(extractPath, finalPath); + return move(extractPath, finalPath); } }); } function download (url, destinationPath) { - const file = fs.createWriteStream(destinationPath); // Will replace any existing file - return new Promise((resolve, reject) => { - const httpx = url.startsWith('https:') ? https : http; + url = url.toLowerCase(); + + let httpx; + + if (url.startsWith('https:')) { + httpx = https; + } else if (url.startsWith('http:')) { + httpx = http; + } else { + reject(`Aborted attempt to download non-HTTP/HTTPS URL ${url}`); + return; + } + + const file = fs.createWriteStream(destinationPath); // Will replace any existing file httpx.get(url, response => { var size = 0; @@ -107,11 +128,15 @@ function download (url, destinationPath) { if (size > MAX_DOWNLOADED_FILE_SIZE_BYTES) { response.destroy(); response.unpipe(file); - fsUnlink(destinationPath); + remove(destinationPath); reject(`File download aborted: exceeded maximum size of ${MAX_DOWNLOADED_FILE_SIZE_BYTES} bytes`); } }); + response.on('error', (e) => { + reject(`File download failed: ${e}`); + }); + response.pipe(file); file.on('finish', () => { @@ -128,11 +153,12 @@ function hashDownload (hash, url, zip = false) { const finalPath = path.join(getHashFetchPath(), 'files', hash); return download(url, tempPath) - // Don't register a failed attempt if the download failed; the user might be offline. - .then(() => checkHashMatch(hash, tempPath).catch(e => registerFailedAttemptAndThrow(hash, url, e))) + .then(() => checkHashMatch(hash, tempPath)) + // @TODO Don't register a failed attempt if the download failed becuse the user was offline. + .catch(e => registerFailedAttemptAndThrow(hash, url, e)) .then(() => { // Hashes match if (!zip) { - return fsRename(tempPath, finalPath); + return move(tempPath, finalPath); } else { const extractPath = path.join(getHashFetchPath(), 'partial-extract', tempFilename); @@ -224,8 +250,15 @@ export default class HashFetch { }); } - // Returns a Promise that resolves with the path to the file or directory. - // `expected` is either 'file' or 'dapp'. + /** + * Download a file or dapp based on its contents hash; + * returns a promise of the path to the downloaded file or directory. + * + * @param {String} api + * @param {String} hash - Keccak256 hexadecimal hash of the file without 0x + * @param {String} expected - Either 'file' or 'dapp' + * @return {Promise} A Promise that resolves with the path to the file or directory + */ fetch (api, hash, expected) { hash = hash.toLowerCase(); @@ -235,7 +268,7 @@ export default class HashFetch { const filePath = path.join(getHashFetchPath(), 'files', hash); if (!(hash in this.promises)) { // There is no ongoing or resolved fetch for this hash - this.promises[hash] = fsExists(filePath) + this.promises[hash] = pathExists(filePath) .catch(() => queryRegistryAndDownload(api, hash, expected)) .then(() => checkExpectedMatch(hash, filePath, expected)) .then(() => filePath) From 90ce81b05cfcc989fbfe8dcad9a5acde3e92c6a7 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Tue, 3 Jul 2018 18:55:20 +0200 Subject: [PATCH 11/14] Restrict in-frame navigation for dapps (#146) * Restrict in-frame navigation for dapps * Lint --- electron/index.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/electron/index.js b/electron/index.js index 3c1884314..f3add4792 100644 --- a/electron/index.js +++ b/electron/index.js @@ -30,6 +30,7 @@ const { getLocalDappsPath } = require('./utils/paths'); const { name: appName } = require('../package.json'); const { app, BrowserWindow, ipcMain, session } = electron; +const { URL } = url; let mainWindow; @@ -113,6 +114,49 @@ function createWindow () { webPreferences.contextIsolation = true; }); + // Listen to the creation of (dapp) webviews to attach event listeners to them + mainWindow.webContents.on('did-attach-webview', (event, webContents) => { + let baseUrl; + let appId; + + // Keep track of the first URL of the webview (index.html of the dapp). + // This defines what files the webview is allowed to navigate to within + // the same frame. For example, my-dapp/index.html can navigate to + // my-dapp/some/folder/hi.html and then back to my-dapp/index.html + webContents.once('did-navigate', (e, initialUrl) => { + const initialURL = new URL(initialUrl); + + appId = initialURL.searchParams.get('appId'); + + initialURL.hash = ''; + initialURL.search = ''; + + baseUrl = initialURL.href.substr(0, initialURL.href.lastIndexOf('/') + 1); + }); + + // The event handler for will-navigate needs to be set in the main process + // in order to be able to prevent the navigation: https://git.io/f4SNW + webContents.on('will-navigate', (e, targetUrl) => { + e.preventDefault(); + + if (targetUrl.startsWith(baseUrl)) { + // The target URL is located inside the dapp folder: allow in-frame + // navigation but enforce appId query parameter for inject.js + + const newURL = new URL(targetUrl); + + newURL.searchParams.set('appId', appId); + + webContents.loadURL(newURL.href); + } else { + // Open all links to resources outside the dapp root in the browser + // (or with the default desktop app for protocols other than http) + + electron.shell.openExternal(targetUrl); + } + }); + }); + mainWindow.on('closed', () => { mainWindow = null; }); From 51ffdacb4a08c92e801f419ba13934a171f25953 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Tue, 3 Jul 2018 21:25:10 +0200 Subject: [PATCH 12/14] Grumbles --- electron/index.js | 24 ++++++++---------------- src/inject.js | 3 +-- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/electron/index.js b/electron/index.js index f3add4792..14f61cb37 100644 --- a/electron/index.js +++ b/electron/index.js @@ -84,22 +84,6 @@ function createWindow () { callback({ requestHeaders: details.requestHeaders }); }); - // Do not accept all kind of web permissions (camera, location...) - // https://electronjs.org/docs/tutorial/security#4-handle-session-permission-requests-from-remote-content - session.defaultSession - .setPermissionRequestHandler((webContents, permission, callback) => { - if (!webContents.getURL().startsWith('file:')) { - // Denies the permissions request for all non-file://. Currently all - // network dapps are loaded on http://127.0.0.1:8545, so they won't - // have any permissions. - return callback(false); - } - - // All others loaded on file:// (shell, builtin, local) can have those - // permissions. - return callback(true); - }); - // Verify WebView Options Before Creation // https://electronjs.org/docs/tutorial/security#12-verify-webview-options-before-creation mainWindow.webContents.on('will-attach-webview', (event, webPreferences, params) => { @@ -116,6 +100,14 @@ function createWindow () { // Listen to the creation of (dapp) webviews to attach event listeners to them mainWindow.webContents.on('did-attach-webview', (event, webContents) => { + // Do not accept all kinds of web permissions (camera, location...) + // https://electronjs.org/docs/tutorial/security#4-handle-session-permission-requests-from-remote-content + webContents.session + .setPermissionRequestHandler((webContents, permission, callback) => { + // Deny all permissions for dapps + return callback(false); + }); + let baseUrl; let appId; diff --git a/src/inject.js b/src/inject.js index dbfbf07e9..843d0a0c2 100644 --- a/src/inject.js +++ b/src/inject.js @@ -81,10 +81,9 @@ if (typeof window !== 'undefined' && !window.isParity) { // https://electronjs.org/docs/tutorial/security#7-override-and-disable-eval // // TODO Currently Web3 Console dapp needs eval(), so we cannot blindly disable - // it as per the recommendation. + // it as per the recommendation. For now we simply allow eval() for all dapps. // One idea is to check here in inject.js if allowJsEval is set to true, but // this requires more work (future PR). - // For now we simply allow eval() for all dapps. // // window.eval = global.eval = function () { // eslint-disable-line // throw new Error(`Sorry, this app does not support window.eval().`); From 3db6aa7127b90c92b0d1ef0a9b520746f0539b71 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Tue, 3 Jul 2018 21:46:51 +0200 Subject: [PATCH 13/14] fs-extra pathExists doesn't throw if the path doesn't exist --- src/util/hashFetch/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/hashFetch/index.js b/src/util/hashFetch/index.js index 0ed47db36..3d88b1846 100644 --- a/src/util/hashFetch/index.js +++ b/src/util/hashFetch/index.js @@ -24,10 +24,11 @@ import { getHashFetchPath } from '../host'; import ExpoRetry from './expoRetry'; import Contracts from '@parity/shared/lib/contracts'; import { bytesToHex } from '@parity/api/lib/util/format'; -import { ensureDir as fsEnsureDir, emptyDir as fsEmptyDir, move, pathExists, remove } from 'fs-extra'; +import { ensureDir as fsEnsureDir, emptyDir as fsEmptyDir, move, remove } from 'fs-extra'; import { http, https } from 'follow-redirects'; import { keccak256 } from 'js-sha3'; +const fsExists = util.promisify(fs.stat); const fsStat = util.promisify(fs.stat); const fsReaddir = util.promisify(fs.readdir); @@ -268,7 +269,7 @@ export default class HashFetch { const filePath = path.join(getHashFetchPath(), 'files', hash); if (!(hash in this.promises)) { // There is no ongoing or resolved fetch for this hash - this.promises[hash] = pathExists(filePath) + this.promises[hash] = fsExists(filePath) .catch(() => queryRegistryAndDownload(api, hash, expected)) .then(() => checkExpectedMatch(hash, filePath, expected)) .then(() => filePath) From 532df40fbedc97045783c8c267dfafb7f590b426 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 4 Jul 2018 15:23:09 +0200 Subject: [PATCH 14/14] Fix bug uglifyjs --- package-lock.json | 661 ++++++++++++++++++++++++++++++++++++++++------ package.json | 1 + webpack/shared.js | 14 +- 3 files changed, 590 insertions(+), 86 deletions(-) diff --git a/package-lock.json b/package-lock.json index 32c58ec44..18f9a3a5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1007,6 +1007,54 @@ "has-flag": "^2.0.0" } }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, "webpack": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.4.1.tgz", @@ -1037,6 +1085,17 @@ "yargs": "^8.0.2" }, "dependencies": { + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + } + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -1078,6 +1137,12 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, "yargs-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", @@ -4684,6 +4749,35 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + } + } + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -5447,6 +5541,20 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, "copy-to-clipboard": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz", @@ -6222,6 +6330,12 @@ "array-find-index": "^1.0.1" } }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -10211,6 +10325,16 @@ "integrity": "sha1-Bq1/4Z3dsQQiZEOAZKKjL+4SuHI=", "dev": true }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, "follow-redirects": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", @@ -10308,6 +10432,16 @@ "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", "dev": true }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, "fs-extra": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", @@ -10356,6 +10490,18 @@ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", "dev": true }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -10391,8 +10537,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.1.1", @@ -10466,7 +10611,6 @@ "version": "2.10.1", "bundled": true, "dev": true, - "optional": true, "requires": { "hoek": "2.x.x" } @@ -10483,8 +10627,7 @@ "buffer-shims": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "caseless": { "version": "0.12.0", @@ -10501,14 +10644,12 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "combined-stream": { "version": "1.0.5", "bundled": true, "dev": true, - "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -10521,14 +10662,12 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "cryptiles": { "version": "2.0.5", @@ -10574,8 +10713,7 @@ "delayed-stream": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "delegates": { "version": "1.0.0", @@ -10601,8 +10739,7 @@ "extsprintf": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "forever-agent": { "version": "0.6.1", @@ -10736,8 +10873,7 @@ "hoek": { "version": "2.16.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "http-signature": { "version": "1.1.1", @@ -10774,7 +10910,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10788,8 +10923,7 @@ "isarray": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "isstream": { "version": "0.1.2", @@ -10862,14 +10996,12 @@ "mime-db": { "version": "1.27.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "mime-types": { "version": "2.1.15", "bundled": true, "dev": true, - "optional": true, "requires": { "mime-db": "~1.27.0" } @@ -10943,8 +11075,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "oauth-sign": { "version": "0.8.2", @@ -11002,8 +11133,7 @@ "process-nextick-args": { "version": "1.0.7", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "punycode": { "version": "1.4.1", @@ -11041,7 +11171,6 @@ "version": "2.2.9", "bundled": true, "dev": true, - "optional": true, "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -11093,8 +11222,7 @@ "safe-buffer": { "version": "5.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "semver": { "version": "5.3.0", @@ -11152,7 +11280,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -11163,7 +11290,6 @@ "version": "1.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -11178,7 +11304,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -11248,8 +11373,7 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "uuid": { "version": "3.0.1", @@ -12409,6 +12533,12 @@ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", @@ -14948,6 +15078,46 @@ "is-plain-obj": "^1.1.0" } }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -15095,6 +15265,20 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -15886,6 +16070,17 @@ "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", "dev": true }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, "param-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", @@ -16804,6 +16999,48 @@ "has-flag": "^2.0.0" } }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, "url-loader": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.6.2.tgz", @@ -16843,6 +17080,19 @@ "watchpack": "^1.4.0", "webpack-sources": "^1.0.1", "yargs": "^8.0.2" + }, + "dependencies": { + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + } + } } }, "webpack-dev-server": { @@ -17038,6 +17288,18 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -18978,6 +19240,12 @@ "asap": "~2.0.3" } }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "promise-worker": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/promise-worker/-/promise-worker-1.1.1.tgz", @@ -19047,6 +19315,29 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -20301,6 +20592,48 @@ "has-flag": "^1.0.0" } }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, "url-loader": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.6.2.tgz", @@ -20356,6 +20689,17 @@ "requires": { "has-flag": "^2.0.0" } + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + } } } }, @@ -20567,6 +20911,18 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -21470,6 +21826,15 @@ "is-promise": "^2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -21736,6 +22101,12 @@ "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=", "dev": true }, + "serialize-javascript": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", + "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -22246,6 +22617,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, "stackframe": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", @@ -22304,6 +22684,16 @@ "readable-stream": "^2.0.2" } }, + "stream-each": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, "stream-http": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", @@ -24067,66 +24457,96 @@ "dev": true }, "uglifyjs-webpack-plugin": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", - "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.7.tgz", + "integrity": "sha512-1VicfKhCYHLS8m1DCApqBhoulnASsEoJ/BvpUpP4zoNAPpKzdH+ghk0olGJMmwX2/jprK2j3hAHdUbczBSy2FA==", "dev": true, "requires": { - "source-map": "^0.5.6", - "uglify-js": "^2.8.29", - "webpack-sources": "^1.0.1" + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "schema-utils": "^0.4.5", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "uglify-es": "^3.3.4", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" }, "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "ajv": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.1" } }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + } }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "punycode": "^2.1.0" } } } @@ -24200,6 +24620,24 @@ "integrity": "sha1-khD5vcqsxeHjkpSQ18AZ35bxhxI=", "dev": true }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-stream": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", @@ -24939,12 +25377,77 @@ "has-flag": "^2.0.0" } }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", diff --git a/package.json b/package.json index ed72c7491..325e64db4 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,7 @@ "stylelint-config-standard": "16.0.0", "to-source": "2.0.3", "uglify-js": "2.8.22", + "uglifyjs-webpack-plugin": "1.2.7", "url-loader": "0.5.7", "webpack": "3.5.5", "webpack-bundle-size-analyzer": "2.5.0", diff --git a/webpack/shared.js b/webpack/shared.js index d7857db54..ee093ff57 100644 --- a/webpack/shared.js +++ b/webpack/shared.js @@ -15,6 +15,7 @@ // along with Parity. If not, see . const webpack = require('webpack'); +const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const HappyPack = require('happypack'); const PackageJson = require('../package.json'); @@ -57,14 +58,13 @@ function getPlugins (_isProd = isProd) { if (_isProd) { plugins.push( new webpack.optimize.ModuleConcatenationPlugin(), - new webpack.optimize.UglifyJsPlugin({ + new UglifyJsPlugin({ sourceMap: true, - screwIe8: true, - compress: { - warnings: false - }, - output: { - comments: false + uglifyOptions: { + ecma: 8, + compress: { + warnings: false + } } }) );