1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 17:33:23 +01:00

Build - refactor for bundle factoring and swappable runtime (#11080)

* wip

* build - breakout sentry-install bundle

* deps - move new build sys deps to published versions

* chore: lint fix

* clean - remove unused file

* clean - remove unsused package script

* lavamoat - update build system policy

* build - render html to all platforms

* development - improve sourcemap debugger output

* deps - update lavapack

* lint - fix

* deps - update lavapack for bugfix

* deps - update lavapack for bugfix

* deps - bump lavapack for line ending normalization

* sourcemap explorer - disable boundary validation

* ci - reset normal ci flow

* build - re-enable minification on prod

* build - remove noisy log about html dest

* build - update terser and remove gulp wrapper for sourcemap fix

* Revert "sourcemap explorer - disable boundary validation"

This reverts commit 94112209ed880a6ebf4ee2ded411e59db6908162.

* build - reenable react-devtools in dev mode

* wip

* build - breakout sentry-install bundle

* deps - move new build sys deps to published versions

* chore: lint fix

* clean - remove unused file

* clean - remove unsused package script

* lavamoat - update build system policy

* build - render html to all platforms

* development - improve sourcemap debugger output

* deps - update lavapack

* lint - fix

* deps - update lavapack for bugfix

* deps - update lavapack for bugfix

* deps - bump lavapack for line ending normalization

* sourcemap explorer - disable boundary validation

* ci - reset normal ci flow

* build - re-enable minification on prod

* build - remove noisy log about html dest

* build - update terser and remove gulp wrapper for sourcemap fix

* Revert "sourcemap explorer - disable boundary validation"

This reverts commit 94112209ed880a6ebf4ee2ded411e59db6908162.

* build - reenable react-devtools in dev mode

* Updating lockfile

* lint fix

* build/dev - patch watchifys incompatible binary stats output

* ui - add comment about conditional import

* build - improve comment

* Update development/stream-flat-map.js

Co-authored-by: Brad Decker <git@braddecker.dev>

* Outputting all bundle file links (metamaskbot)

Co-authored-by: ryanml <ryanlanese@gmail.com>
Co-authored-by: Brad Decker <git@braddecker.dev>
This commit is contained in:
kumavis 2021-07-15 10:59:34 -07:00 committed by GitHub
parent 4aab4887d5
commit 9f4820ee98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 586 additions and 472 deletions

View File

@ -154,7 +154,7 @@ module.exports = {
'babel.config.js',
'nyc.config.js',
'stylelint.config.js',
'app/scripts/runLockdown.js',
'app/scripts/lockdown-run.js',
'development/**/*.js',
'test/e2e/**/*.js',
'test/lib/wait-until-called.js',

View File

@ -5,11 +5,13 @@
</head>
<body>
<script src="./globalthis.js" type="text/javascript" charset="utf-8"></script>
<script src="./initSentry.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./runLockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./bg-libs.js" type="text/javascript" charset="utf-8"></script>
<script src="./background.js" type="text/javascript" charset="utf-8"></script>
<script src="./sentry-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-run.js" type="text/javascript" charset="utf-8"></script>
<script src="./runtime-cjs.js" type="text/javascript" charset="utf-8"></script>
{{@each(it.jsBundles) => val}}
<script src="{{val}}" type="text/javascript" charset="utf-8"></script>
{{/each}}
<script src="./chromereload.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>

View File

@ -11,10 +11,12 @@
<div id="app-content"></div>
<div id="popover-content"></div>
<script src="./globalthis.js" type="text/javascript" charset="utf-8"></script>
<script src="./initSentry.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./runLockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./ui-libs.js" type="text/javascript" charset="utf-8"></script>
<script src="./ui.js" type="text/javascript" charset="utf-8"></script>
<script src="./sentry-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-run.js" type="text/javascript" charset="utf-8"></script>
<script src="./runtime-cjs.js" type="text/javascript" charset="utf-8"></script>
{{@each(it.jsBundles) => val}}
<script src="{{val}}" type="text/javascript" charset="utf-8"></script>
{{/each}}
</body>
</html>

View File

@ -33,8 +33,8 @@
"js": [
"disable-console.js",
"globalthis.js",
"lockdown.js",
"runLockdown.js",
"lockdown-install.js",
"lockdown-run.js",
"contentscript.js"
],
"run_at": "document_start",

View File

@ -34,10 +34,12 @@
</div>
<div id="popover-content"></div>
<script src="./globalthis.js" type="text/javascript" charset="utf-8"></script>
<script src="./initSentry.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./runLockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./ui-libs.js" type="text/javascript" charset="utf-8"></script>
<script src="./ui.js" type="text/javascript" charset="utf-8"></script>
<script src="./sentry-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-run.js" type="text/javascript" charset="utf-8"></script>
<script src="./runtime-cjs.js" type="text/javascript" charset="utf-8"></script>
{{@each(it.jsBundles) => val}}
<script src="{{val}}" type="text/javascript" charset="utf-8"></script>
{{/each}}
</body>
</html>

View File

@ -3,8 +3,8 @@
<head>
<title>Ethereum Phishing Detection - MetaMask</title>
<script src="./globalthis.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./runLockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-run.js" type="text/javascript" charset="utf-8"></script>
<script src="./phishing-detect.js"></script>
<link rel="stylesheet" type="text/css" href="./index.css" title="ltr">
<link rel="stylesheet" type="text/css" href="./index-rtl.css" title="rtl" disabled>

View File

@ -11,10 +11,12 @@
<div id="app-content"></div>
<div id="popover-content"></div>
<script src="./globalthis.js" type="text/javascript" charset="utf-8"></script>
<script src="./initSentry.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./runLockdown.js" type="text/javascript" charset="utf-8"></script>
<script src="./ui-libs.js" type="text/javascript" charset="utf-8"></script>
<script src="./ui.js" type="text/javascript" charset="utf-8"></script>
<script src="./sentry-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-install.js" type="text/javascript" charset="utf-8"></script>
<script src="./lockdown-run.js" type="text/javascript" charset="utf-8"></script>
<script src="./runtime-cjs.js" type="text/javascript" charset="utf-8"></script>
{{@each(it.jsBundles) => val}}
<script src="{{val}}" type="text/javascript" charset="utf-8"></script>
{{/each}}
</body>
</html>

View File

@ -14,7 +14,7 @@ try {
// caught and logged here so that the contentscript still gets injected.
// This affects Firefox v56 and Waterfox Classic
console.error('Lockdown failed:', error);
if (window.sentry && window.sentry.captureException) {
window.sentry.captureException(error);
if (globalThis.sentry && globalThis.sentry.captureException) {
globalThis.sentry.captureException(error);
}
}

View File

@ -2,6 +2,9 @@
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
import '@formatjs/intl-relativetimeformat/polyfill';
// dev only, "react-devtools" import is skipped in prod builds
import 'react-devtools';
import PortStream from 'extension-port-stream';
import extension from 'extensionizer';

View File

@ -1,19 +1,29 @@
const { callbackify } = require('util');
const path = require('path');
const { writeFileSync, readFileSync } = require('fs');
const EventEmitter = require('events');
const gulp = require('gulp');
const watch = require('gulp-watch');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const log = require('fancy-log');
const watchify = require('watchify');
const browserify = require('browserify');
const envify = require('loose-envify/custom');
const sourcemaps = require('gulp-sourcemaps');
const terser = require('gulp-terser-js');
const watchify = require('watchify');
const babelify = require('babelify');
const brfs = require('brfs');
const envify = require('loose-envify/custom');
const sourcemaps = require('gulp-sourcemaps');
const applySourceMap = require('vinyl-sourcemaps-apply');
const pify = require('pify');
const through = require('through2');
const endOfStream = pify(require('end-of-stream'));
const labeledStreamSplicer = require('labeled-stream-splicer').obj;
const wrapInStream = require('pumpify').obj;
const Sqrl = require('squirrelly');
const lavaPack = require('@lavamoat/lavapack');
const terser = require('terser');
const bifyModuleGroups = require('bify-module-groups');
const metamaskrc = require('rc')('metamask', {
INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID,
@ -25,9 +35,8 @@ const metamaskrc = require('rc')('metamask', {
'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496',
});
const { version } = require('../../package.json');
const packageJSON = require('../../package.json');
const { streamFlatMap } = require('../stream-flat-map.js');
const baseManifest = require('../../app/manifest/_base.json');
const {
createTask,
composeParallel,
@ -37,17 +46,6 @@ const {
module.exports = createScriptTasks;
const dependencies = Object.keys(
(packageJSON && packageJSON.dependencies) || {},
);
const materialUIDependencies = ['@material-ui/core'];
const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u));
const externalDependenciesMap = {
background: ['3box', '@ethereumjs/common', 'unicode-confusables'],
ui: [...materialUIDependencies, ...reactDepenendencies],
};
function createScriptTasks({ browserPlatforms, livereload }) {
// internal tasks
const core = {
@ -69,72 +67,43 @@ function createScriptTasks({ browserPlatforms, livereload }) {
// production
prod: createTasksForBuildJsExtension({ taskPrefix: 'scripts:core:prod' }),
};
const deps = {
background: createTasksForBuildJsDeps({
label: 'bg-libs',
key: 'background',
}),
ui: createTasksForBuildJsDeps({ label: 'ui-libs', key: 'ui' }),
};
// high level tasks
const prod = composeParallel(deps.background, deps.ui, core.prod);
const { dev, test, testDev, prod } = core;
return { dev, test, testDev, prod };
const { dev, testDev } = core;
const test = composeParallel(deps.background, deps.ui, core.test);
return { prod, dev, testDev, test };
function createTasksForBuildJsDeps({ key, label }) {
return createTask(
`scripts:deps:${key}`,
createNormalBundle({
label,
destFilepath: `${label}.js`,
modulesToExpose: externalDependenciesMap[key],
devMode: false,
function createTasksForBuildJsExtension({ taskPrefix, devMode, testing }) {
const standardEntryPoints = ['background', 'ui', 'phishing-detect'];
const standardSubtask = createTask(
`${taskPrefix}:standardEntryPoints`,
createFactoredBuild({
entryFiles: standardEntryPoints.map(
(label) => `./app/scripts/${label}.js`,
),
devMode,
testing,
browserPlatforms,
}),
);
}
function createTasksForBuildJsExtension({ taskPrefix, devMode, testing }) {
const standardBundles = [
'background',
'ui',
'phishing-detect',
'initSentry',
];
const standardSubtasks = standardBundles.map((label) => {
let extraEntries;
if (devMode && label === 'ui') {
extraEntries = ['./development/require-react-devtools.js'];
}
return createTask(
`${taskPrefix}:${label}`,
createBundleTaskForBuildJsExtensionNormal({
label,
devMode,
testing,
extraEntries,
}),
);
});
// inpage must be built before contentscript
// because inpage bundle result is included inside contentscript
const contentscriptSubtask = createTask(
`${taskPrefix}:contentscript`,
createTaskForBuildJsExtensionContentscript({ devMode, testing }),
createTaskForBundleContentscript({ devMode, testing }),
);
// this can run whenever
const disableConsoleSubtask = createTask(
`${taskPrefix}:disable-console`,
createTaskForBuildJsExtensionDisableConsole({ devMode }),
createTaskForBundleDisableConsole({ devMode }),
);
// this can run whenever
const installSentrySubtask = createTask(
`${taskPrefix}:sentry`,
createTaskForBundleSentry({ devMode }),
);
// task for initiating browser livereload
@ -155,36 +124,16 @@ function createScriptTasks({ browserPlatforms, livereload }) {
// make each bundle run in a separate process
const allSubtasks = [
...standardSubtasks,
standardSubtask,
contentscriptSubtask,
disableConsoleSubtask,
installSentrySubtask,
].map((subtask) => runInChildProcess(subtask));
// const allSubtasks = [...standardSubtasks, contentscriptSubtask].map(subtask => (subtask))
// make a parent task that runs each task in a child thread
return composeParallel(initiateLiveReload, ...allSubtasks);
}
function createBundleTaskForBuildJsExtensionNormal({
label,
devMode,
testing,
extraEntries,
}) {
return createNormalBundle({
label,
entryFilepath: `./app/scripts/${label}.js`,
destFilepath: `${label}.js`,
extraEntries,
externalDependencies: devMode
? undefined
: externalDependenciesMap[label],
devMode,
testing,
browserPlatforms,
});
}
function createTaskForBuildJsExtensionDisableConsole({ devMode }) {
function createTaskForBundleDisableConsole({ devMode }) {
const label = 'disable-console';
return createNormalBundle({
label,
@ -195,7 +144,19 @@ function createScriptTasks({ browserPlatforms, livereload }) {
});
}
function createTaskForBuildJsExtensionContentscript({ devMode, testing }) {
function createTaskForBundleSentry({ devMode }) {
const label = 'sentry-install';
return createNormalBundle({
label,
entryFilepath: `./app/scripts/${label}.js`,
destFilepath: `${label}.js`,
devMode,
browserPlatforms,
});
}
// the "contentscript" bundle contains the "inpage" bundle
function createTaskForBundleContentscript({ devMode, testing }) {
const inpage = 'inpage';
const contentscript = 'contentscript';
return composeSeries(
@ -203,9 +164,6 @@ function createScriptTasks({ browserPlatforms, livereload }) {
label: inpage,
entryFilepath: `./app/scripts/${inpage}.js`,
destFilepath: `${inpage}.js`,
externalDependencies: devMode
? undefined
: externalDependenciesMap[inpage],
devMode,
testing,
browserPlatforms,
@ -214,9 +172,6 @@ function createScriptTasks({ browserPlatforms, livereload }) {
label: contentscript,
entryFilepath: `./app/scripts/${contentscript}.js`,
destFilepath: `${contentscript}.js`,
externalDependencies: devMode
? undefined
: externalDependenciesMap[contentscript],
devMode,
testing,
browserPlatforms,
@ -225,12 +180,8 @@ function createScriptTasks({ browserPlatforms, livereload }) {
}
}
function createNormalBundle({
destFilepath,
entryFilepath,
extraEntries = [],
modulesToExpose,
externalDependencies,
function createFactoredBuild({
entryFiles,
devMode,
testing,
browserPlatforms,
@ -240,10 +191,126 @@ function createNormalBundle({
const buildConfiguration = createBuildConfiguration();
const { bundlerOpts, events } = buildConfiguration;
// devMode options
const reloadOnChange = Boolean(devMode);
const minify = Boolean(devMode) === false;
const envVars = getEnvironmentVariables({ devMode, testing });
setupBundlerDefaults(buildConfiguration, {
devMode,
envVars,
reloadOnChange,
minify,
});
// set bundle entries
bundlerOpts.entries = [...entryFiles];
// setup bundle factoring with bify-module-groups plugin
Object.assign(bundlerOpts, bifyModuleGroups.plugin.args);
bundlerOpts.plugin = [...bundlerOpts.plugin, [bifyModuleGroups.plugin]];
// instrument pipeline
let sizeGroupMap;
events.on('configurePipeline', ({ pipeline }) => {
// to be populated by the group-by-size transform
sizeGroupMap = new Map();
pipeline.get('groups').unshift(
// factor modules
bifyModuleGroups.groupByFactor({
entryFileToLabel(filepath) {
return path.parse(filepath).name;
},
}),
// cap files at 2 mb
bifyModuleGroups.groupBySize({
sizeLimit: 2e6,
groupingMap: sizeGroupMap,
}),
);
pipeline.get('vinyl').unshift(
// convert each module group into a stream with a single vinyl file
streamFlatMap((moduleGroup) => {
const filename = `${moduleGroup.label}.js`;
const childStream = wrapInStream(
moduleGroup.stream,
lavaPack({ raw: true, hasExports: true, includePrelude: false }),
source(filename),
);
return childStream;
}),
buffer(),
);
// setup bundle destination
browserPlatforms.forEach((platform) => {
const dest = `./dist/${platform}/`;
pipeline.get('dest').push(gulp.dest(dest));
});
});
// wait for bundle completion for postprocessing
events.on('bundleDone', () => {
const commonSet = sizeGroupMap.get('common');
// create entry points for each file
for (const [groupLabel, groupSet] of sizeGroupMap.entries()) {
// skip "common" group, they are added tp all other groups
if (groupSet === commonSet) continue;
switch (groupLabel) {
case 'ui': {
renderHtmlFile('popup', groupSet, commonSet, browserPlatforms);
renderHtmlFile(
'notification',
groupSet,
commonSet,
browserPlatforms,
);
renderHtmlFile('home', groupSet, commonSet, browserPlatforms);
break;
}
case 'phishing-detect': {
renderHtmlFile('phishing', groupSet, commonSet, browserPlatforms);
break;
}
case 'background': {
renderHtmlFile('background', groupSet, commonSet, browserPlatforms);
break;
}
default: {
throw new Error(`buildsys - unknown groupLabel "${groupLabel}"`);
}
}
}
});
await bundleIt(buildConfiguration);
};
}
function createNormalBundle({
destFilepath,
entryFilepath,
extraEntries = [],
modulesToExpose,
devMode,
testing,
browserPlatforms,
}) {
return async function () {
// create bundler setup and apply defaults
const buildConfiguration = createBuildConfiguration();
const { bundlerOpts, events } = buildConfiguration;
// devMode options
const reloadOnChange = Boolean(devMode);
const minify = Boolean(devMode) === false;
const envVars = getEnvironmentVariables({ devMode, testing });
setupBundlerDefaults(buildConfiguration, {
devMode,
envVars,
reloadOnChange,
minify,
});
// set bundle entries
@ -256,14 +323,6 @@ function createNormalBundle({
bundlerOpts.require = bundlerOpts.require.concat(modulesToExpose);
}
if (externalDependencies) {
// there doesnt seem to be a standard bify option for this
// so we'll put it here but manually call it after bundle
bundlerOpts.manualExternal = bundlerOpts.manualExternal.concat(
externalDependencies,
);
}
// instrument pipeline
events.on('configurePipeline', ({ pipeline }) => {
// convert bundle stream to gulp vinyl stream
@ -288,17 +347,18 @@ function createBuildConfiguration() {
transform: [],
plugin: [],
require: [],
// not a standard bify option
// non-standard bify options
manualExternal: [],
manualIgnore: [],
};
return { bundlerOpts, events };
}
function setupBundlerDefaults(buildConfiguration, { devMode, envVars }) {
function setupBundlerDefaults(
buildConfiguration,
{ devMode, envVars, reloadOnChange, minify },
) {
const { bundlerOpts } = buildConfiguration;
// devMode options
const reloadOnChange = Boolean(devMode);
const minify = Boolean(devMode) === false;
Object.assign(bundlerOpts, {
// source transforms
@ -314,6 +374,11 @@ function setupBundlerDefaults(buildConfiguration, { devMode, envVars }) {
debug: true,
});
// ensure react-devtools are not included in non-dev builds
if (!devMode) {
bundlerOpts.manualIgnore.push('react-devtools');
}
// inject environment variables via node-style `process.env`
if (envVars) {
bundlerOpts.transform.push([envify(envVars), { global: true }]);
@ -351,17 +416,33 @@ function setupReloadOnChange({ bundlerOpts, events }) {
}
function setupMinification(buildConfiguration) {
const minifyOpts = {
mangle: {
reserved: ['MetamaskInpageProvider'],
},
};
const { events } = buildConfiguration;
events.on('configurePipeline', ({ pipeline }) => {
pipeline.get('minify').push(
terser({
mangle: {
reserved: ['MetamaskInpageProvider'],
},
sourceMap: {
content: true,
},
}),
// this is the "gulp-terser-js" wrapper around the latest version of terser
through.obj(
callbackify(async (file, _enc) => {
const input = {
[file.sourceMap.file]: file.contents.toString(),
};
const opts = {
sourceMap: {
filename: file.sourceMap.file,
content: file.sourceMap,
},
...minifyOpts,
};
const res = await terser.minify(input, opts);
file.contents = Buffer.from(res.code);
applySourceMap(file, res.map);
return file;
}),
),
);
});
}
@ -385,18 +466,22 @@ function setupSourcemaps(buildConfiguration, { devMode }) {
async function bundleIt(buildConfiguration) {
const { bundlerOpts, events } = buildConfiguration;
const bundler = browserify(bundlerOpts);
// manually apply non-standard option
// manually apply non-standard options
bundler.external(bundlerOpts.manualExternal);
bundler.ignore(bundlerOpts.manualIgnore);
// output build logs to terminal
bundler.on('log', log);
// forward update event (used by watchify)
bundler.on('update', () => performBundle());
await performBundle();
async function performBundle() {
// this pipeline is created for every bundle
// the labels are all the steps you can hook into
const pipeline = labeledStreamSplicer([
'groups',
[],
'vinyl',
[],
'sourcemaps:init',
@ -415,7 +500,11 @@ async function bundleIt(buildConfiguration) {
bundleStream.pipe(pipeline);
// nothing will consume pipeline, so let it flow
pipeline.resume();
await endOfStream(pipeline);
// call the completion event to handle any post-processing
events.emit('bundleDone');
}
}
@ -427,7 +516,7 @@ function getEnvironmentVariables({ devMode, testing }) {
return {
METAMASK_DEBUG: devMode,
METAMASK_ENVIRONMENT: environment,
METAMASK_VERSION: version,
METAMASK_VERSION: baseManifest.version,
NODE_ENV: devMode ? 'development' : 'production',
IN_TEST: testing ? 'true' : false,
PUBNUB_SUB_KEY: process.env.PUBNUB_SUB_KEY || '',
@ -478,6 +567,20 @@ function getEnvironment({ devMode, testing }) {
return 'other';
}
function renderHtmlFile(htmlName, groupSet, commonSet, browserPlatforms) {
const htmlFilePath = `./app/${htmlName}.html`;
const htmlTemplate = readFileSync(htmlFilePath, 'utf8');
const jsBundles = [...commonSet.values(), ...groupSet.values()].map(
(label) => `./${label}.js`,
);
const htmlOutput = Sqrl.render(htmlTemplate, { jsBundles });
browserPlatforms.forEach((platform) => {
const dest = `./dist/${platform}/${htmlName}.html`;
// we dont have a way of creating async events atm
writeFileSync(dest, htmlOutput);
});
}
function beep() {
process.stdout.write('\x07');
}

View File

@ -40,9 +40,8 @@ const copyTargets = [
dest: ``,
},
{
src: `./app/`,
pattern: `*.html`,
dest: ``,
src: `./app/loading.html`,
dest: `loading.html`,
},
{
src: `./node_modules/globalthis/dist/browser.js`,
@ -50,12 +49,16 @@ const copyTargets = [
},
{
src: `./node_modules/ses/dist/lockdown.cjs`,
dest: `lockdown.js`,
dest: `lockdown-install.js`,
},
{
src: `./app/scripts/`,
pattern: `runLockdown.js`,
dest: ``,
src: `./app/scripts/lockdown-run.js`,
dest: `lockdown-run.js`,
},
{
// eslint-disable-next-line node/no-extraneous-require
src: require.resolve('@lavamoat/lavapack/src/runtime-cjs.js'),
dest: `runtime-cjs.js`,
},
];

View File

@ -71,8 +71,9 @@ function runInChildProcess(task) {
let childProcess;
// don't run subprocesses in lavamoat for dev mode if main process not run in lavamoat
if (
taskName.includes('scripts:core:dev') &&
!process.argv[0].includes('lavamoat')
process.env.npm_lifecycle_event === 'build:dev' ||
(taskName.includes('scripts:core:dev') &&
!process.argv[0].includes('lavamoat'))
) {
childProcess = spawn('yarn', ['build:dev', taskName, '--skip-stats'], {
env: process.env,

View File

@ -2,6 +2,7 @@
const { promises: fs } = require('fs');
const path = require('path');
const fetch = require('node-fetch');
const glob = require('fast-glob');
const VERSION = require('../dist/chrome/manifest.json').version; // eslint-disable-line import/no-unresolved
start().catch(console.error);
@ -39,19 +40,15 @@ async function start() {
.join(', ');
// links to bundle browser builds
const bundles = [
'background',
'ui',
'inpage',
'contentscript',
'ui-libs',
'bg-libs',
'phishing-detect',
];
const bundleLinks = bundles
.map((bundle) => {
const url = `${BUILD_LINK_BASE}/build-artifacts/source-map-explorer/${bundle}.html`;
return `<a href="${url}">${bundle}</a>`;
const fileType = '.html';
const sourceMapRoot = '/build-artifacts/source-map-explorer/';
const bundleFiles = await glob(`.${sourceMapRoot}*${fileType}`);
const bundleLinks = bundleFiles
.map((bundleFile) => {
const fileName = bundleFile.split(sourceMapRoot)[1];
const bundleName = fileName.split(fileType)[0];
const url = `${BUILD_LINK_BASE}${sourceMapRoot}${fileName}`;
return `<a href="${url}">${bundleName}</a>`;
})
.join(', ');

View File

@ -1 +0,0 @@
require('react-devtools');

View File

@ -2,6 +2,7 @@ const fs = require('fs');
const path = require('path');
const { SourceMapConsumer } = require('source-map');
const pify = require('pify');
const { codeFrameColumns } = require('@babel/code-frame');
const fsAsync = pify(fs);
@ -20,13 +21,12 @@ start().catch((error) => {
async function start() {
const targetFiles = [
`background.js`,
// `bg-libs`, skipped because source maps are invalid due to browserify bug: https://github.com/browserify/browserify/issues/1971
`common-0.js`,
`background-0.js`,
`ui-0.js`,
'phishing-detect-0.js',
// `contentscript.js`, skipped because the validator is erroneously sampling the inlined `inpage.js` script
`inpage.js`,
'phishing-detect.js',
`ui.js`,
// `ui-libs.js`, skipped because source maps are invalid due to browserify bug: https://github.com/browserify/browserify/issues/1971
];
let valid = true;
@ -102,7 +102,6 @@ async function validateSourcemapForFile({ buildName }) {
const buildLines = rawBuild.split('\n');
const targetString = 'new Error';
// const targetString = 'null'
const matchesPerLine = buildLines.map((line) =>
indicesOf(targetString, line),
);
@ -114,26 +113,35 @@ async function validateSourcemapForFile({ buildName }) {
// warn if source content is missing
if (!result.source) {
valid = false;
console.warn(
`!! missing source for position: ${JSON.stringify(position)}`,
const location = {
start: { line: position.line, column: position.column + 1 },
};
const codeSample = codeFrameColumns(rawBuild, location, {
message: `missing source for position`,
highlightCode: true,
});
console.error(
`missing source for position, in bundle "${buildName}"\n${codeSample}`,
);
// const buildLine = buildLines[position.line - 1]
console.warn(` origin in build:`);
console.warn(` ${buildLines[position.line - 2]}`);
console.warn(`-> ${buildLines[position.line - 1]}`);
console.warn(` ${buildLines[position.line - 0]}`);
return;
}
const sourceContent = consumer.sourceContentFor(result.source);
const sourceLines = sourceContent.split('\n');
const line = sourceLines[result.line - 1];
const sourceLine = sourceLines[result.line - 1];
// this sometimes includes the whole line though we tried to match somewhere in the middle
const portion = line.slice(result.column);
const isMaybeValid = portion.includes(targetString);
if (!isMaybeValid) {
const portion = sourceLine.slice(result.column);
const foundValidSource = portion.includes(targetString);
if (!foundValidSource) {
valid = false;
const location = {
start: { line: result.line + 1, column: result.column + 1 },
};
const codeSample = codeFrameColumns(sourceContent, location, {
message: `expected to see ${JSON.stringify(targetString)}`,
highlightCode: true,
});
console.error(
`Sourcemap seems invalid:\n${getFencedCode(result.source, line)}`,
`Sourcemap seems invalid, ${result.source}\n${codeSample}`,
);
}
});
@ -142,27 +150,6 @@ async function validateSourcemapForFile({ buildName }) {
return valid;
}
const CODE_FENCE_LENGTH = 80;
const TITLE_PADDING_LENGTH = 1;
function getFencedCode(filename, code) {
const title = `${' '.repeat(TITLE_PADDING_LENGTH)}${filename}${' '.repeat(
TITLE_PADDING_LENGTH,
)}`;
const openingFenceLength = Math.max(
CODE_FENCE_LENGTH - (filename.length + TITLE_PADDING_LENGTH * 2),
0,
);
const startOpeningFenceLength = Math.floor(openingFenceLength / 2);
const endOpeningFenceLength = Math.ceil(openingFenceLength / 2);
const openingFence = `${'='.repeat(
startOpeningFenceLength,
)}${title}${'='.repeat(endOpeningFenceLength)}`;
const closingFence = '='.repeat(CODE_FENCE_LENGTH);
return `${openingFence}\n${code}\n${closingFence}\n`;
}
function indicesOf(substring, string) {
const a = [];
let i = -1;

View File

@ -0,0 +1,43 @@
const { PassThrough: ThroughStream } = require('stream');
// eslint-ignore-next-line node/no-extraneous-require
const duplexify = require('duplexify').obj;
module.exports = {
streamFlatMap,
asyncGeneratorToStream,
};
// returns an async generator that maps each chunk to a stream with the specified
// "entryToStream" mapping fn, and forwards child streams out
// useable with streams.pipeline
function streamFlatMap(entryToStream) {
const duplex = asyncGeneratorToStream(flatMapGenerator);
return duplex;
async function* flatMapGenerator(source) {
for await (const entry of source) {
const subStream = entryToStream(entry);
yield* subStream;
}
}
}
// this stupid utility turns an async iterator factory into a duplex stream
function asyncGeneratorToStream(factoryFn) {
const writableStream = new ThroughStream({ objectMode: true });
const readableStream = new ThroughStream({ objectMode: true });
const duplex = duplexify(writableStream, readableStream);
const asyncIter = factoryFn(writableStream);
// drain iterator into readable stream
process.nextTick(async () => {
try {
for await (const item of asyncIter) {
readableStream.write(item);
}
readableStream.end();
} catch (err) {
readableStream.destroy(err);
}
});
return duplex;
}

View File

@ -223,11 +223,6 @@
"js-tokens": true
}
},
"@babel/parser": {
"globals": {
"BigInt": true
}
},
"@babel/plugin-proposal-async-generator-functions": {
"packages": {
"@babel/core": true,
@ -805,6 +800,26 @@
"through2": true
}
},
"@lavamoat/lavapack": {
"builtin": {
"assert": true,
"buffer.Buffer.from": true,
"path.join": true,
"path.relative": true
},
"globals": {
"__dirname": true,
"process.cwd": true
},
"packages": {
"JSONStream": true,
"combine-source-map": true,
"convert-source-map": true,
"json-stable-stringify": true,
"through2": true,
"umd": true
}
},
"@nodelib/fs.scandir": {
"builtin": {
"fs.lstat": true,
@ -874,7 +889,6 @@
},
"acorn": {
"globals": {
"BigInt": true,
"define": true
}
},
@ -884,9 +898,6 @@
}
},
"acorn-node": {
"globals": {
"BigInt": true
},
"packages": {
"acorn": true,
"acorn-dynamic-import": true,
@ -959,16 +970,6 @@
"buffer-equal": true
}
},
"are-we-there-yet": {
"builtin": {
"events.EventEmitter": true,
"util.inherits": true
},
"packages": {
"delegates": true,
"readable-stream": true
}
},
"arr-diff": {
"packages": {
"arr-flatten": true,
@ -1091,6 +1092,13 @@
"pascalcase": true
}
},
"bify-module-groups": {
"packages": {
"pify": true,
"pump": true,
"through2": true
}
},
"bl": {
"builtin": {
"util.inherits": true
@ -1321,7 +1329,6 @@
"anymatch": true,
"async-each": true,
"braces": true,
"fsevents": true,
"glob-parent": true,
"inherits": true,
"is-binary-path": true,
@ -1573,16 +1580,6 @@
"through2": true
}
},
"detect-libc": {
"builtin": {
"child_process.spawnSync": true,
"fs.readdirSync": true,
"os.platform": true
},
"globals": {
"process.env": true
}
},
"detective": {
"packages": {
"acorn-node": true,
@ -1670,10 +1667,7 @@
"es-abstract": {
"globals": {
"AggregateError": true,
"Atomics": true,
"BigInt": true,
"FinalizationRegistry": true,
"SharedArrayBuffer": true,
"WeakRef": true
},
"packages": {
@ -2026,45 +2020,6 @@
"process.version": true
}
},
"fsevents": {
"builtin": {
"events.EventEmitter": true,
"fs.stat": true,
"path.join": true,
"util.inherits": true
},
"globals": {
"__dirname": true,
"process.nextTick": true,
"process.platform": true,
"setImmediate": true
},
"native": true,
"packages": {
"node-pre-gyp": true
}
},
"gauge": {
"builtin": {
"util.format": true
},
"globals": {
"clearInterval": true,
"process": true,
"setImmediate": true,
"setInterval": true
},
"packages": {
"aproba": true,
"console-control-strings": true,
"has-unicode": true,
"object-assign": true,
"signal-exit": true,
"string-width": true,
"strip-ansi": true,
"wide-align": true
}
},
"get-assigned-identifiers": {
"builtin": {
"assert.equal": true
@ -2375,26 +2330,6 @@
"through2": true
}
},
"gulp-terser-js": {
"builtin": {
"fs.readFileSync": true,
"path.basename": true,
"path.resolve": true
},
"globals": {
"Buffer.from": true,
"console.error": true,
"console.log": true,
"process.stdout.columns": true
},
"packages": {
"plugin-error": true,
"source-map": true,
"terser": true,
"through2": true,
"vinyl-sourcemaps-apply": true
}
},
"gulp-watch": {
"builtin": {
"path.dirname": true,
@ -2445,16 +2380,6 @@
"process.argv": true
}
},
"has-unicode": {
"builtin": {
"os.type": true
},
"globals": {
"process.env.LANG": true,
"process.env.LC_ALL": true,
"process.env.LC_CTYPE": true
}
},
"has-value": {
"packages": {
"get-value": true,
@ -2608,11 +2533,6 @@
"is-plain-object": true
}
},
"is-fullwidth-code-point": {
"packages": {
"number-is-nan": true
}
},
"is-glob": {
"packages": {
"is-extglob": true
@ -2997,56 +2917,6 @@
"setTimeout": true
}
},
"node-pre-gyp": {
"builtin": {
"events.EventEmitter": true,
"fs.existsSync": true,
"fs.readFileSync": true,
"fs.renameSync": true,
"path.dirname": true,
"path.existsSync": true,
"path.join": true,
"path.resolve": true,
"url.parse": true,
"url.resolve": true,
"util.inherits": true
},
"globals": {
"__dirname": true,
"console.log": true,
"process.arch": true,
"process.cwd": true,
"process.env": true,
"process.platform": true,
"process.version.substr": true,
"process.versions": true
},
"packages": {
"detect-libc": true,
"nopt": true,
"npmlog": true,
"rimraf": true,
"semver": true
}
},
"nopt": {
"builtin": {
"path": true,
"stream.Stream": true,
"url": true
},
"globals": {
"console": true,
"process.argv": true,
"process.env.DEBUG_NOPT": true,
"process.env.NOPT_DEBUG": true,
"process.platform": true
},
"packages": {
"abbrev": true,
"osenv": true
}
},
"normalize-path": {
"packages": {
"remove-trailing-separator": true
@ -3062,22 +2932,6 @@
"once": true
}
},
"npmlog": {
"builtin": {
"events.EventEmitter": true,
"util": true
},
"globals": {
"process.nextTick": true,
"process.stderr": true
},
"packages": {
"are-we-there-yet": true,
"console-control-strings": true,
"gauge": true,
"set-blocking": true
}
},
"object-copy": {
"packages": {
"copy-descriptor": true,
@ -3090,7 +2944,6 @@
"util.inspect": true
},
"globals": {
"BigInt": true,
"HTMLElement": true
}
},
@ -3145,54 +2998,6 @@
"readable-stream": true
}
},
"os-homedir": {
"builtin": {
"os.homedir": true
},
"globals": {
"process.env": true,
"process.getuid": true,
"process.platform": true
}
},
"os-tmpdir": {
"globals": {
"process.env.SystemRoot": true,
"process.env.TEMP": true,
"process.env.TMP": true,
"process.env.TMPDIR": true,
"process.env.windir": true,
"process.platform": true
}
},
"osenv": {
"builtin": {
"child_process.exec": true,
"path": true
},
"globals": {
"process.env.COMPUTERNAME": true,
"process.env.ComSpec": true,
"process.env.EDITOR": true,
"process.env.HOSTNAME": true,
"process.env.PATH": true,
"process.env.PROMPT": true,
"process.env.PS1": true,
"process.env.Path": true,
"process.env.SHELL": true,
"process.env.USER": true,
"process.env.USERDOMAIN": true,
"process.env.USERNAME": true,
"process.env.VISUAL": true,
"process.env.path": true,
"process.nextTick": true,
"process.platform": true
},
"packages": {
"os-homedir": true,
"os-tmpdir": true
}
},
"parent-module": {
"packages": {
"callsites": true
@ -3775,12 +3580,6 @@
"process": true
}
},
"set-blocking": {
"globals": {
"process.stderr": true,
"process.stdout": true
}
},
"set-value": {
"packages": {
"extend-shallow": true,
@ -3910,6 +3709,15 @@
"extend-shallow": true
}
},
"squirrelly": {
"builtin": {
"fs.existsSync": true,
"fs.readFileSync": true,
"path.dirname": true,
"path.extname": true,
"path.resolve": true
}
},
"static-eval": {
"packages": {
"escodegen": true
@ -3974,7 +3782,6 @@
},
"string-width": {
"packages": {
"code-point-at": true,
"emoji-regex": true,
"is-fullwidth-code-point": true,
"strip-ansi": true
@ -4130,9 +3937,19 @@
"Buffer.from": true,
"atob": true,
"btoa": true,
"define": true
"console.log": true,
"console.warn": true,
"define": true,
"process.argv": true,
"process.exit": true,
"process.platform": true,
"process.stderr.write": true,
"process.stdin.on": true,
"process.stdin.resume": true,
"process.stdin.setEncoding": true
},
"packages": {
"acorn": true,
"source-map": true
}
},
@ -4531,11 +4348,6 @@
"isexe": true
}
},
"wide-align": {
"packages": {
"string-width": true
}
},
"write": {
"builtin": {
"fs.createWriteStream": true,

View File

@ -9,7 +9,7 @@
"scripts": {
"setup": "yarn install && yarn setup:postinstall",
"setup:postinstall": "yarn patch-package && yarn allow-scripts",
"start": "node development/build/index.js dev",
"start": "yarn build:dev dev",
"start:lavamoat": "yarn build dev",
"dist": "yarn build prod",
"build": "lavamoat development/build/index.js",
@ -191,6 +191,7 @@
"readable-stream": "^2.3.3",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"requirejs": "^2.3.6",
"reselect": "^3.0.1",
"rpc-cap": "^3.2.1",
"safe-event-emitter": "^1.0.1",
@ -204,6 +205,7 @@
"web3-stream-provider": "^4.0.0"
},
"devDependencies": {
"@babel/code-frame": "^7.12.13",
"@babel/core": "^7.12.1",
"@babel/eslint-parser": "^7.13.14",
"@babel/eslint-plugin": "^7.12.1",
@ -216,6 +218,7 @@
"@babel/preset-react": "^7.0.0",
"@babel/register": "^7.5.5",
"@lavamoat/allow-scripts": "^1.0.6",
"@lavamoat/lavapack": "^1.0.4",
"@metamask/auto-changelog": "^2.1.0",
"@metamask/eslint-config": "^6.0.0",
"@metamask/eslint-config-jest": "^6.0.0",
@ -237,7 +240,10 @@
"@types/react": "^16.9.53",
"addons-linter": "1.14.0",
"babelify": "^10.0.0",
"bify-module-groups": "^1.0.0",
"bify-vinyl-gator": "^1.0.0",
"brfs": "^2.0.2",
"browser-pack": "^6.1.0",
"browserify": "^16.5.1",
"chalk": "^3.0.0",
"chromedriver": "^79.0.0",
@ -247,6 +253,7 @@
"css-loader": "^2.1.1",
"css-to-xpath": "^0.1.0",
"del": "^3.0.0",
"duplexify": "^4.1.1",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"eslint": "^7.23.0",
@ -273,7 +280,6 @@
"gulp-rtlcss": "^1.4.0",
"gulp-sourcemaps": "^2.6.0",
"gulp-stylelint": "^13.0.0",
"gulp-terser-js": "^5.2.2",
"gulp-watch": "^5.0.1",
"gulp-zip": "^4.0.0",
"history": "^5.0.0",
@ -293,6 +299,7 @@
"prettier": "^2.2.1",
"prettier-plugin-sort-json": "^0.0.1",
"proxyquire": "^2.1.3",
"pumpify": "^2.0.1",
"randomcolor": "^0.5.4",
"rc": "^1.2.8",
"react-devtools": "^4.10.1",
@ -308,13 +315,16 @@
"sinon": "^9.0.0",
"source-map": "^0.7.2",
"source-map-explorer": "^2.4.2",
"squirrelly": "^8.0.8",
"string.prototype.matchall": "^4.0.2",
"style-loader": "^0.21.0",
"stylelint": "^13.6.1",
"through2": "^2.0.3",
"terser": "^5.7.0",
"through2": "^4.0.2",
"ttest": "^2.1.1",
"vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0",
"vinyl-sourcemaps-apply": "^0.2.1",
"watchify": "^3.11.1",
"webpack": "^4.41.6",
"yargs": "^17.0.1"

View File

@ -0,0 +1,13 @@
diff --git a/node_modules/squirrelly/dist/squirrelly.cjs.js b/node_modules/squirrelly/dist/squirrelly.cjs.js
index 7908a34..044e348 100644
--- a/node_modules/squirrelly/dist/squirrelly.cjs.js
+++ b/node_modules/squirrelly/dist/squirrelly.cjs.js
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
// TODO: allow '-' to trim up until newline. Use [^\S\n\r] instead of \s
// TODO: only include trimLeft polyfill if not in ES6
/* END TYPES */
-var promiseImpl = new Function('return this')().Promise;
+var promiseImpl = globalThis.Promise;
var asyncFunc = false;
try {
asyncFunc = new Function('return (async function(){}).constructor')();

View File

@ -0,0 +1,38 @@
diff --git a/node_modules/watchify/index.js b/node_modules/watchify/index.js
index 0753b9f..4fea9e1 100644
--- a/node_modules/watchify/index.js
+++ b/node_modules/watchify/index.js
@@ -58,33 +58,6 @@ function watchify (b, opts) {
if (pkgcache) pkgcache[file] = pkg;
});
- b.on('reset', reset);
- reset();
-
- function reset () {
- var time = null;
- var bytes = 0;
- b.pipeline.get('record').on('end', function () {
- time = Date.now();
- });
-
- b.pipeline.get('wrap').push(through(write, end));
- function write (buf, enc, next) {
- bytes += buf.length;
- this.push(buf);
- next();
- }
- function end () {
- var delta = Date.now() - time;
- b.emit('time', delta);
- b.emit('bytes', bytes);
- b.emit('log', bytes + ' bytes written ('
- + (delta / 1000).toFixed(2) + ' seconds)'
- );
- this.push(null);
- }
- }
-
var fwatchers = {};
var fwatcherFiles = {};
var ignoredFiles = {};

View File

@ -1,7 +1,7 @@
// Should occur before anything else
import './globalPatch';
import 'ses/lockdown';
import '../../app/scripts/runLockdown';
import '../../app/scripts/lockdown-run';
import { strict as assert } from 'assert'; /* eslint-disable-line import/first,import/order */
describe('Promise global is immutable', function () {

133
yarn.lock
View File

@ -2567,6 +2567,18 @@
semver "^7.3.4"
yargs "^16.2.0"
"@lavamoat/lavapack@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@lavamoat/lavapack/-/lavapack-1.0.4.tgz#e72d6b29fa70da8236a127c1d95cb581cda6941e"
integrity sha512-Zhcn+eJyHIS4AAmN9IIjs8WCh12Q7NpFXXz0pI3Y54uknTdx5TPlwr3ARKf0jEXDOWNok/TuK2uPld54BSG/FQ==
dependencies:
JSONStream "^1.3.5"
combine-source-map "^0.8.0"
convert-source-map "^1.7.0"
json-stable-stringify "^1.0.1"
through2 "^4.0.2"
umd "^3.0.3"
"@lavamoat/preinstall-always-fail@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@lavamoat/preinstall-always-fail/-/preinstall-always-fail-1.0.0.tgz#e78a6e3d9e212a4fef869ec37d4f5fb498dea373"
@ -4299,7 +4311,7 @@
optionalDependencies:
text-encoding "^0.6.4"
JSONStream@^1.0.3:
JSONStream@^1.0.3, JSONStream@^1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
@ -6435,6 +6447,33 @@ better-opn@^2.0.0:
dependencies:
open "^7.0.3"
bify-module-groups@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/bify-module-groups/-/bify-module-groups-1.0.0.tgz#6fba8f96a8b0f9e8f0b04035650fd56249b6119d"
integrity sha512-JAAkE9L5vZoALCEqawXipQNlDn3D0nUyjt0cHgRXj0Kce2RNLQsBxA6wTmnYpQDna6g6VVyC8IUi3n02ppmbhA==
dependencies:
bify-packagedata-stream "1.0.0"
pump "^3.0.0"
through2 "^3.0.1"
bify-packagedata-stream@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/bify-packagedata-stream/-/bify-packagedata-stream-1.0.0.tgz#a6dbdcba64f9bf1c87bdc02ba9586fff7b94ccb3"
integrity sha512-ckOCceDpAOySFrt89saOShpVbP/iQbmZeWlYSxZV2e3HPTPhcd3JSudMJZhpsihQTyZut39efDo4+8aOb4vo2w==
dependencies:
module-name-from-path "git+https://git@github.com/kumavis/module-name-from-path.git"
resolve-package-path "^1.2.7"
through2 "^3.0.0"
bify-vinyl-gator@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/bify-vinyl-gator/-/bify-vinyl-gator-1.0.0.tgz#aa1ce5c6a5829c75250fea6b04ec6a45c558efde"
integrity sha512-mGR/U+veqIrMWRWV1TUayNEmSIhaGDggYLwIBwDA7v2bTSHrEZcyyLs6FN3cF2cuyCzvpV1w4eH6P/So0nhCbA==
dependencies:
requirejs "^2.3.6"
through2 "^4.0.2"
vinyl "^2.2.1"
big-integer@1.6.36:
version "1.6.36"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36"
@ -6792,7 +6831,7 @@ brorand@^1.0.1, brorand@^1.0.5, brorand@^1.1.0:
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
browser-pack@^6.0.1:
browser-pack@^6.0.1, browser-pack@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774"
integrity sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==
@ -9556,6 +9595,16 @@ duplexify@^3.1.2, duplexify@^3.4.2:
readable-stream "^2.0.0"
stream-shift "^1.0.0"
duplexify@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61"
integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==
dependencies:
end-of-stream "^1.4.1"
inherits "^2.0.3"
readable-stream "^3.1.1"
stream-shift "^1.0.0"
each-props@^1.3.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333"
@ -13225,17 +13274,6 @@ gulp-stylelint@^13.0.0:
strip-ansi "^6.0.0"
through2 "^3.0.1"
gulp-terser-js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/gulp-terser-js/-/gulp-terser-js-5.2.2.tgz#3d93db9b2b83f35dfcc5b209af6b1762756eb6a3"
integrity sha512-4ull0HzTWeWjRPiGmAFmdhRcEDOG+r7aXivNHOBQzElLzMaeVKQwmCPDi2juBzUUkjAkPkKb1jHVoJN/PKTvcA==
dependencies:
plugin-error "^1.0.1"
source-map "^0.7.3"
terser "^4.6.12"
through2 "^3.0.1"
vinyl-sourcemaps-apply "^0.2.1"
gulp-watch@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/gulp-watch/-/gulp-watch-5.0.1.tgz#83d378752f5bfb46da023e73c17ed1da7066215d"
@ -18548,6 +18586,10 @@ module-deps@^6.0.0:
through2 "^2.0.0"
xtend "^4.0.0"
"module-name-from-path@git+https://git@github.com/kumavis/module-name-from-path.git":
version "1.0.4"
resolved "git+https://git@github.com/kumavis/module-name-from-path.git#fd9c592663a1af6cc48b1be7b8045ea547fca79a"
module-not-found-error@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0"
@ -21605,6 +21647,15 @@ pumpify@^1.3.3, pumpify@^1.3.5:
inherits "^2.0.1"
pump "^1.0.0"
pumpify@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e"
integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==
dependencies:
duplexify "^4.1.1"
inherits "^2.0.3"
pump "^3.0.0"
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
@ -22354,7 +22405,7 @@ readable-stream@1.1.x, readable-stream@^1.0.33:
isarray "0.0.1"
string_decoder "~0.10.x"
"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.0.2, readable-stream@^3.0.5, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.0.2, readable-stream@^3.0.5, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@ -22919,6 +22970,11 @@ require-uncached@^1.0.2:
caller-path "^0.1.0"
resolve-from "^1.0.0"
requirejs@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
reselect@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147"
@ -22971,6 +23027,14 @@ resolve-options@^1.1.0:
dependencies:
value-or-function "^3.0.0"
resolve-package-path@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-1.2.7.tgz#2a7bc37ad96865e239330e3102c31322847e652e"
integrity sha512-fVEKHGeK85bGbVFuwO9o1aU0n3vqQGrezPc51JGu9UTXpFQfWq5qCeKxyaRUSvephs+06c5j5rPq/dzHGEo8+Q==
dependencies:
path-root "^0.1.1"
resolve "^1.10.0"
resolve-pathname@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
@ -24188,7 +24252,7 @@ source-map-support@^0.4.15:
dependencies:
source-map "^0.5.6"
source-map-support@^0.5.11, source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.4:
source-map-support@^0.5.11, source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.19, source-map-support@~0.5.4:
version "0.5.19"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
@ -24206,7 +24270,7 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@0.X, source-map@^0.7.2, source-map@^0.7.3:
source-map@0.X, source-map@^0.7.2, source-map@^0.7.3, source-map@~0.7.2:
version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
@ -24313,6 +24377,11 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
squirrelly@^8.0.8:
version "8.0.8"
resolved "https://registry.yarnpkg.com/squirrelly/-/squirrelly-8.0.8.tgz#d6704650b2170b8040d5de5bff9fa69cb62b5e0f"
integrity sha512-7dyZJ9Gw86MmH0dYLiESsjGOTj6KG8IWToTaqBuB6LwPI+hyNb6mbQaZwrfnAQ4cMDnSWMUvX/zAYDLTSWLk/w==
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
@ -25257,7 +25326,7 @@ terser-webpack-plugin@^3.0.0:
terser "^4.8.0"
webpack-sources "^1.4.3"
terser@^4.1.2, terser@^4.6.12, terser@^4.6.3, terser@^4.8.0:
terser@^4.1.2, terser@^4.6.3, terser@^4.8.0:
version "4.8.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17"
integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==
@ -25266,6 +25335,15 @@ terser@^4.1.2, terser@^4.6.12, terser@^4.6.3, terser@^4.8.0:
source-map "~0.6.1"
source-map-support "~0.5.12"
terser@^5.7.0:
version "5.7.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693"
integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==
dependencies:
commander "^2.20.0"
source-map "~0.7.2"
source-map-support "~0.5.19"
test-exclude@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
@ -25323,6 +25401,13 @@ through2@^3.0.0, through2@^3.0.1:
dependencies:
readable-stream "2 || 3"
through2@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764"
integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==
dependencies:
readable-stream "3"
through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@ -25868,7 +25953,7 @@ typical@^5.0.0:
resolved "https://registry.yarnpkg.com/typical/-/typical-5.1.0.tgz#7116ca103caf2574985fc84fbaa8fd0ee5ea1684"
integrity sha512-t5Ik8UAwBal1P1XzuVE4dc+RYQZicLUGJdvqr/vdqsED7SQECgsGBylldSsfWZL7RQjxT3xhQcKHWhLaVSR6YQ==
umd@^3.0.0:
umd@^3.0.0, umd@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf"
integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==
@ -26566,6 +26651,18 @@ vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.0:
remove-trailing-separator "^1.0.1"
replace-ext "^1.0.0"
vinyl@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974"
integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==
dependencies:
clone "^2.1.1"
clone-buffer "^1.0.0"
clone-stats "^1.0.0"
cloneable-readable "^1.0.0"
remove-trailing-separator "^1.0.1"
replace-ext "^1.0.0"
vm-browserify@^1.0.0, vm-browserify@^1.0.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"