diff --git a/app/attachments.js b/app/attachments.js index 148f6bebac..b04a673044 100644 --- a/app/attachments.js +++ b/app/attachments.js @@ -2,8 +2,7 @@ const crypto = require('crypto'); const path = require('path'); const { app, dialog, shell, remote } = require('electron'); -const pify = require('pify'); -const glob = require('glob'); +const fastGlob = require('fast-glob'); const fse = require('fs-extra'); const toArrayBuffer = require('to-arraybuffer'); const { map, isArrayBuffer, isString } = require('lodash'); @@ -28,7 +27,7 @@ exports.getAllAttachments = async userDataPath => { const dir = exports.getPath(userDataPath); const pattern = path.join(dir, '**', '*'); - const files = await pify(glob)(pattern, { nodir: true }); + const files = await fastGlob(pattern, { onlyFiles: true }); return map(files, file => path.relative(dir, file)); }; @@ -36,7 +35,7 @@ exports.getAllStickers = async userDataPath => { const dir = exports.getStickersPath(userDataPath); const pattern = path.join(dir, '**', '*'); - const files = await pify(glob)(pattern, { nodir: true }); + const files = await fastGlob(pattern, { onlyFiles: true }); return map(files, file => path.relative(dir, file)); }; @@ -44,7 +43,7 @@ exports.getAllDraftAttachments = async userDataPath => { const dir = exports.getDraftPath(userDataPath); const pattern = path.join(dir, '**', '*'); - const files = await pify(glob)(pattern, { nodir: true }); + const files = await fastGlob(pattern, { onlyFiles: true }); return map(files, file => path.relative(dir, file)); }; @@ -52,7 +51,7 @@ exports.getBuiltInImages = async () => { const dir = path.join(__dirname, '../images'); const pattern = path.join(dir, '**', '*.svg'); - const files = await pify(glob)(pattern, { nodir: true }); + const files = await fastGlob(pattern, { onlyFiles: true }); return map(files, file => path.relative(dir, file)); }; diff --git a/js/background.js b/js/background.js index e03ee9d34d..baf7a53ad2 100644 --- a/js/background.js +++ b/js/background.js @@ -500,6 +500,8 @@ if (newVersion) { await window.Signal.Data.cleanupOrphanedAttachments(); + // Don't block on the following operation + window.Signal.Data.ensureFilePermissions(); } Views.Initialization.setMessage(window.i18n('loading')); diff --git a/js/modules/data.js b/js/modules/data.js index e212555752..6779b609ce 100644 --- a/js/modules/data.js +++ b/js/modules/data.js @@ -33,6 +33,7 @@ const ERASE_STICKERS_KEY = 'erase-stickers'; const ERASE_TEMP_KEY = 'erase-temp'; const ERASE_DRAFTS_KEY = 'erase-drafts'; const CLEANUP_ORPHANED_ATTACHMENTS_KEY = 'cleanup-orphaned-attachments'; +const ENSURE_FILE_PERMISSIONS = 'ensure-file-permissions'; const _jobs = Object.create(null); const _DEBUG = false; @@ -169,6 +170,7 @@ module.exports = { removeOtherData, cleanupOrphanedAttachments, + ensureFilePermissions, // Returning plain JSON getMessagesNeedingUpgrade, @@ -1043,6 +1045,10 @@ async function cleanupOrphanedAttachments() { await callChannel(CLEANUP_ORPHANED_ATTACHMENTS_KEY); } +async function ensureFilePermissions() { + await callChannel(ENSURE_FILE_PERMISSIONS); +} + // Note: will need to restart the app after calling this, to set up afresh async function removeOtherData() { await Promise.all([ diff --git a/main.js b/main.js index 1d969c4848..d8845825fb 100644 --- a/main.js +++ b/main.js @@ -3,9 +3,12 @@ const path = require('path'); const url = require('url'); const os = require('os'); -const fs = require('fs'); +const fs = require('fs-extra'); const crypto = require('crypto'); const qs = require('qs'); +const normalizePath = require('normalize-path'); +const fg = require('fast-glob'); +const PQueue = require('p-queue').default; const _ = require('lodash'); const pify = require('pify'); @@ -16,6 +19,10 @@ const GlobalErrors = require('./app/global_errors'); GlobalErrors.addHandler(); +// Set umask early on in the process lifecycle to ensure file permissions are +// set such that only we have read access to our files +process.umask(0o077); + const getRealPath = pify(fs.realpath); const { app, @@ -863,6 +870,8 @@ app.on('ready', async () => { } setupMenu(); + + ensureFilePermissions(['config.json', 'sql/db.sqlite']); }); function setupMenu(options) { @@ -1195,3 +1204,51 @@ ipc.on('install-sticker-pack', (_event, packId, packKeyHex) => { const packKey = Buffer.from(packKeyHex, 'hex').toString('base64'); mainWindow.webContents.send('install-sticker-pack', { packId, packKey }); }); + +ipc.on('ensure-file-permissions', async event => { + await ensureFilePermissions(); + event.reply('ensure-file-permissions-done'); +}); + +/** + * Ensure files in the user's data directory have the proper permissions. + * Optionally takes an array of file paths to exclusively affect. + * + * @param {string[]} [onlyFiles] - Only ensure permissions on these given files + */ +async function ensureFilePermissions(onlyFiles) { + console.log('Begin ensuring permissions'); + + const start = Date.now(); + const userDataPath = await getRealPath(app.getPath('userData')); + // fast-glob uses `/` for all platforms + const userDataGlob = normalizePath(path.join(userDataPath, '**', '*')); + + // Determine files to touch + const files = onlyFiles + ? onlyFiles.map(f => path.join(userDataPath, f)) + : await fg(userDataGlob, { + markDirectories: true, + onlyFiles: false, + ignore: ['**/Singleton*'], + }); + + console.log(`Ensuring file permissions for ${files.length} files`); + + // Touch each file in a queue + const q = new PQueue({ concurrency: 5 }); + q.addAll( + files.map(f => async () => { + const isDir = f.endsWith('/'); + try { + await fs.chmod(path.normalize(f), isDir ? 0o700 : 0o600); + } catch (error) { + console.error('ensureFilePermissions: Error from chmod', error.message); + } + }) + ); + + await q.onEmpty(); + + console.log(`Finish ensuring permissions in ${Date.now() - start}ms`); +} diff --git a/package.json b/package.json index 44e8a8501f..41c6818524 100644 --- a/package.json +++ b/package.json @@ -82,12 +82,12 @@ "emoji-datasource": "5.0.1", "emoji-datasource-apple": "5.0.1", "emoji-regex": "8.0.0", + "fast-glob": "3.2.1", "filesize": "3.6.1", "firstline": "1.2.1", "form-data": "2.3.2", "fs-extra": "5.0.0", "fuse.js": "3.4.4", - "glob": "7.1.2", "google-libphonenumber": "3.2.6", "got": "8.2.0", "he": "1.2.0", @@ -103,6 +103,7 @@ "mustache": "2.3.0", "node-fetch": "https://github.com/scottnonnenberg-signal/node-fetch.git#3e5f51e08c647ee5f20c43b15cf2d352d61c36b4", "node-gyp": "5.0.3", + "normalize-path": "3.0.0", "os-locale": "2.1.0", "p-map": "2.1.0", "p-queue": "6.2.1", @@ -148,7 +149,7 @@ "devDependencies": { "@babel/core": "7.7.7", "@babel/plugin-proposal-class-properties": "7.7.4", - "@babel/plugin-transform-runtime": "^7.8.3", + "@babel/plugin-transform-runtime": "7.8.3", "@babel/preset-react": "7.7.4", "@babel/preset-typescript": "7.7.7", "@storybook/addon-actions": "5.1.11", @@ -199,7 +200,7 @@ "babel-plugin-lodash": "3.3.4", "bower": "1.8.2", "chai": "4.1.2", - "core-js": "^2.4.0", + "core-js": "2.4.0", "cross-env": "5.2.0", "css-loader": "3.2.0", "dashdash": "1.14.1", diff --git a/preload.js b/preload.js index a877a2c367..d69a9c8be4 100644 --- a/preload.js +++ b/preload.js @@ -397,7 +397,7 @@ require('./js/spell_check'); if (config.environment === 'test') { /* eslint-disable global-require, import/no-extraneous-dependencies */ window.test = { - glob: require('glob'), + fastGlob: require('fast-glob'), fse: require('fs-extra'), tmp: require('tmp'), path: require('path'), diff --git a/test/backup_test.js b/test/backup_test.js index 7d97e835fd..e5a8ca78f1 100644 --- a/test/backup_test.js +++ b/test/backup_test.js @@ -239,7 +239,7 @@ describe('Backup', () => { it('exports then imports to produce the same data we started with', async function thisNeeded() { this.timeout(6000); - const { attachmentsPath, fse, glob, path, tmp } = window.test; + const { attachmentsPath, fse, fastGlob, path, tmp } = window.test; const { upgradeMessageSchema, loadAttachmentData, @@ -509,7 +509,7 @@ describe('Backup', () => { console.log( 'Backup test: Ensure that all attachments were saved to disk' ); - const attachmentFiles = removeDirs(glob.sync(attachmentsPattern)); + const attachmentFiles = removeDirs(fastGlob.sync(attachmentsPattern)); console.log({ attachmentFiles }); assert.strictEqual(ATTACHMENT_COUNT, attachmentFiles.length); @@ -529,7 +529,7 @@ describe('Backup', () => { 'Backup test: Ensure that all attachments made it to backup dir' ); const backupAttachmentPattern = path.join(backupDir, 'attachments/*'); - const backupAttachments = glob.sync(backupAttachmentPattern); + const backupAttachments = fastGlob.sync(backupAttachmentPattern); console.log({ backupAttachments }); assert.strictEqual(ATTACHMENT_COUNT, backupAttachments.length); @@ -568,7 +568,7 @@ describe('Backup', () => { console.log('Backup test: ensure that all attachments were imported'); const recreatedAttachmentFiles = removeDirs( - glob.sync(attachmentsPattern) + fastGlob.sync(attachmentsPattern) ); console.log({ recreatedAttachmentFiles }); assert.strictEqual(ATTACHMENT_COUNT, recreatedAttachmentFiles.length); diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index 5ff02d0ca9..f30a45ff90 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -3397,6 +3397,62 @@ "reasonCategory": "falseMatch", "updated": "2018-09-19T18:13:29.628Z" }, + { + "rule": "jQuery-append(", + "path": "node_modules/fast-glob/node_modules/braces/lib/expand.js", + "line": " result.push(append(value, stash, enclose));", + "lineNumber": 21, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/fast-glob/node_modules/braces/lib/expand.js", + "line": " result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele));", + "lineNumber": 26, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/fast-glob/node_modules/braces/lib/expand.js", + "line": " q.push(append(q.pop(), stringify(node, options)));", + "lineNumber": 48, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/fast-glob/node_modules/braces/lib/expand.js", + "line": " q.push(append(q.pop(), ['{}']));", + "lineNumber": 53, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/fast-glob/node_modules/braces/lib/expand.js", + "line": " q.push(append(q.pop(), range));", + "lineNumber": 69, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/fast-glob/node_modules/braces/lib/expand.js", + "line": " q.push(append(q.pop(), queue, enclose));", + "lineNumber": 93, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/fast-glob/node_modules/braces/lib/expand.js", + "line": " queue.push(append(queue.pop(), child.value));", + "lineNumber": 98, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, { "rule": "jQuery-load(", "path": "node_modules/file-entry-cache/cache.js", @@ -10053,6 +10109,38 @@ "reasonCategory": "falseMatch", "updated": "2018-09-19T18:13:29.628Z" }, + { + "rule": "jQuery-append(", + "path": "node_modules/picomatch/lib/parse.js", + "line": " if (tok.value || tok.output) append(tok);", + "lineNumber": 210, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/picomatch/lib/parse.js", + "line": " append({ value });", + "lineNumber": 415, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/picomatch/lib/parse.js", + "line": " append({ value });", + "lineNumber": 427, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, + { + "rule": "jQuery-append(", + "path": "node_modules/picomatch/lib/parse.js", + "line": " append({ value });", + "lineNumber": 511, + "reasonCategory": "falseMatch", + "updated": "2020-02-21T14:09:28.005Z" + }, { "rule": "thenify-multiArgs", "path": "node_modules/pify/index.js", diff --git a/ts/util/lint/linter.ts b/ts/util/lint/linter.ts index 895ac807d7..24268b1c32 100644 --- a/ts/util/lint/linter.ts +++ b/ts/util/lint/linter.ts @@ -3,8 +3,7 @@ import { readFileSync } from 'fs'; import { join, relative } from 'path'; -// @ts-ignore -import * as glob from 'glob'; +import { sync as fgSync } from 'fast-glob'; import { forEach, some, values } from 'lodash'; import { ExceptionType, REASONS, RuleType } from './types'; @@ -44,7 +43,7 @@ const exceptions: Array = loadJSON(exceptionsPath); const exceptionsLookup = createLookup(exceptions); let scannedCount = 0; -const allSourceFiles = glob.sync(searchPattern, { nodir: true }); +const allSourceFiles = fgSync(searchPattern, { onlyFiles: true }); const results: Array = []; diff --git a/yarn.lock b/yarn.lock index 7495c1e69b..cd51e55a5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -823,7 +823,7 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-runtime@^7.8.3": +"@babel/plugin-transform-runtime@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz#c0153bc0a5375ebc1f1591cb7eea223adea9f169" integrity sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ== @@ -1294,11 +1294,32 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -3864,6 +3885,13 @@ braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -5111,6 +5139,11 @@ core-js-pure@^3.0.1: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.2.1.tgz#879a23699cff46175bfd2d09158b5c50645a3c45" integrity sha512-+qpvnYrsi/JDeQTArB7NnNc2VoMYLE1YSkziCDHgjexC2KH7OFiGhLUd3urxfyWmNjSwSW7NYXPWHMhuIJx9Ow== +core-js@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.0.tgz#df408ab46d01aff91c01c3e7971935d422c54f81" + integrity sha1-30CKtG0Br/kcAcPnlxk11CLFT4E= + core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" @@ -7071,6 +7104,18 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-glob@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.1.tgz#c5aaea632f92543b744bdcb19f11efd49e56c7b3" + integrity sha512-XObtOQLTl4EptWcBbO9O6wd17VlVf9YXYY/zuzuu7nZfTsv4BL3KupMAMUVzH88CUwWkI3uNHBfxtfU8PveVTQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-glob@^2.0.2: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" @@ -7095,6 +7140,13 @@ fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + fault@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.3.tgz#4da88cf979b6b792b4e13c7ec836767725170b7e" @@ -7261,6 +7313,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" @@ -7825,6 +7884,13 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" +glob-parent@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" @@ -9345,6 +9411,13 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" +is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + is-hexadecimal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" @@ -9394,6 +9467,11 @@ is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-obj@^1.0.0, is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -10687,6 +10765,11 @@ merge2@^1.2.3: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.4.tgz#c9269589e6885a60cf80605d9522d4b67ca646e3" integrity sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A== +merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -10732,6 +10815,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -11448,17 +11539,17 @@ normalize-package-data@^2.5.0: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-path@3.0.0, normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" @@ -12294,6 +12385,11 @@ phantomjs-prebuilt@^2.1.14: request-progress "^2.0.1" which "^1.2.10" +picomatch@^2.0.5, picomatch@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== + pidtree@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" @@ -14561,6 +14657,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rgb2hex@^0.1.9: version "0.1.9" resolved "https://registry.yarnpkg.com/rgb2hex/-/rgb2hex-0.1.9.tgz#5d3e0e14b0177b568e6f0d5b43e34fbfdb670346" @@ -14620,6 +14721,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -16251,6 +16357,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"