diff --git a/fixtures/flight/loader/index.js b/fixtures/flight/loader/index.js
index b9cfa5b73eee0..04960e6dcc9e1 100644
--- a/fixtures/flight/loader/index.js
+++ b/fixtures/flight/loader/index.js
@@ -1,4 +1,8 @@
-import {resolve, getSource} from 'react-transport-dom-webpack/node-loader';
+import {
+ resolve,
+ getSource,
+ transformSource as reactTransformSource,
+} from 'react-transport-dom-webpack/node-loader';
export {resolve, getSource};
@@ -13,7 +17,7 @@ const babelOptions = {
],
};
-export async function transformSource(source, context, defaultTransformSource) {
+async function babelTransformSource(source, context, defaultTransformSource) {
const {format} = context;
if (format === 'module') {
const opt = Object.assign({filename: context.url}, babelOptions);
@@ -22,3 +26,9 @@ export async function transformSource(source, context, defaultTransformSource) {
}
return defaultTransformSource(source, context, defaultTransformSource);
}
+
+export async function transformSource(source, context, defaultTransformSource) {
+ return reactTransformSource(source, context, (s, c) => {
+ return babelTransformSource(s, c, defaultTransformSource);
+ });
+}
diff --git a/fixtures/flight/server/index.js b/fixtures/flight/server/cli.server.js
similarity index 100%
rename from fixtures/flight/server/index.js
rename to fixtures/flight/server/cli.server.js
diff --git a/fixtures/flight/server/handler.server.js b/fixtures/flight/server/handler.server.js
index d7715af9cc757..86476bb2c2d71 100644
--- a/fixtures/flight/server/handler.server.js
+++ b/fixtures/flight/server/handler.server.js
@@ -17,14 +17,35 @@ module.exports = async function(req, res) {
pipeToNodeWritable(, res, {
// TODO: Read from a map on the disk.
[resolve('../src/Counter.client.js')]: {
- id: './src/Counter.client.js',
- chunks: ['1'],
- name: 'default',
+ Counter: {
+ id: './src/Counter.client.js',
+ chunks: ['2'],
+ name: 'Counter',
+ },
+ },
+ [resolve('../src/Counter2.client.js')]: {
+ Counter: {
+ id: './src/Counter2.client.js',
+ chunks: ['1'],
+ name: 'Counter',
+ },
},
[resolve('../src/ShowMore.client.js')]: {
- id: './src/ShowMore.client.js',
- chunks: ['2'],
- name: 'default',
+ default: {
+ id: './src/ShowMore.client.js',
+ chunks: ['3'],
+ name: 'default',
+ },
+ '': {
+ id: './src/ShowMore.client.js',
+ chunks: ['3'],
+ name: '',
+ },
+ '*': {
+ id: './src/ShowMore.client.js',
+ chunks: ['3'],
+ name: '*',
+ },
},
});
};
diff --git a/fixtures/flight/server/package.json b/fixtures/flight/server/package.json
index 5bbefffbabee3..59055eee7d5bd 100644
--- a/fixtures/flight/server/package.json
+++ b/fixtures/flight/server/package.json
@@ -1,3 +1,4 @@
{
- "type": "commonjs"
+ "type": "commonjs",
+ "main": "./cli.server.js"
}
diff --git a/fixtures/flight/src/App.server.js b/fixtures/flight/src/App.server.js
index 54a644dc48d49..35a223dce8b07 100644
--- a/fixtures/flight/src/App.server.js
+++ b/fixtures/flight/src/App.server.js
@@ -2,7 +2,8 @@ import * as React from 'react';
import Container from './Container.js';
-import Counter from './Counter.client.js';
+import {Counter} from './Counter.client.js';
+import {Counter as Counter2} from './Counter2.client.js';
import ShowMore from './ShowMore.client.js';
@@ -11,6 +12,7 @@ export default function App() {
Hello, world
+
Lorem ipsum
diff --git a/fixtures/flight/src/Counter.client.js b/fixtures/flight/src/Counter.client.js
index 00a1f2cbe440d..676280f0542f6 100644
--- a/fixtures/flight/src/Counter.client.js
+++ b/fixtures/flight/src/Counter.client.js
@@ -2,7 +2,7 @@ import * as React from 'react';
import Container from './Container.js';
-export default function Counter() {
+export function Counter() {
const [count, setCount] = React.useState(0);
return (
diff --git a/fixtures/flight/src/Counter2.client.js b/fixtures/flight/src/Counter2.client.js
new file mode 100644
index 0000000000000..084f7bc5f071d
--- /dev/null
+++ b/fixtures/flight/src/Counter2.client.js
@@ -0,0 +1 @@
+export * from './Counter.client.js';
diff --git a/packages/react-transport-dom-webpack/package.json b/packages/react-transport-dom-webpack/package.json
index a71a558f5160f..8e2db02610eff 100644
--- a/packages/react-transport-dom-webpack/package.json
+++ b/packages/react-transport-dom-webpack/package.json
@@ -50,6 +50,7 @@
"webpack": "^4.43.0"
},
"dependencies": {
+ "acorn": "^6.2.1",
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
},
diff --git a/packages/react-transport-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js b/packages/react-transport-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js
index 3e667960d2620..f3c4e1bf1c16d 100644
--- a/packages/react-transport-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js
+++ b/packages/react-transport-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js
@@ -59,5 +59,16 @@ export function requireModule(moduleData: ModuleReference): T {
throw entry;
}
}
- return __webpack_require__(moduleData.id)[moduleData.name];
+ const moduleExports = __webpack_require__(moduleData.id);
+ if (moduleData.name === '*') {
+ // This is a placeholder value that represents that the caller imported this
+ // as a CommonJS module as is.
+ return moduleExports;
+ }
+ if (moduleData.name === '') {
+ // This is a placeholder value that represents that the caller accessed the
+ // default property of this if it was an ESM interop module.
+ return moduleExports.__esModule ? moduleExports.default : moduleExports;
+ }
+ return moduleExports[moduleData.name];
}
diff --git a/packages/react-transport-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js b/packages/react-transport-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js
index f691809522ca1..c8469eeba8068 100644
--- a/packages/react-transport-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js
+++ b/packages/react-transport-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js
@@ -8,7 +8,9 @@
*/
type WebpackMap = {
- [filename: string]: ModuleMetaData,
+ [filepath: string]: {
+ [name: string]: ModuleMetaData,
+ },
};
export type BundlerConfig = WebpackMap;
@@ -16,6 +18,7 @@ export type BundlerConfig = WebpackMap;
// eslint-disable-next-line no-unused-vars
export type ModuleReference = {
$$typeof: Symbol,
+ filepath: string,
name: string,
};
@@ -30,7 +33,7 @@ export type ModuleKey = string;
const MODULE_TAG = Symbol.for('react.module.reference');
export function getModuleKey(reference: ModuleReference): ModuleKey {
- return reference.name;
+ return reference.filepath + '#' + reference.name;
}
export function isModuleReference(reference: Object): boolean {
@@ -41,5 +44,5 @@ export function resolveModuleMetaData(
config: BundlerConfig,
moduleReference: ModuleReference,
): ModuleMetaData {
- return config[moduleReference.name];
+ return config[moduleReference.filepath][moduleReference.name];
}
diff --git a/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeLoader.js b/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeLoader.js
index f9fd2a54e24f6..d716cda4653cc 100644
--- a/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeLoader.js
+++ b/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeLoader.js
@@ -7,6 +7,8 @@
* @flow
*/
+import acorn from 'acorn';
+
type ResolveContext = {
conditions: Array,
parentURL: string | void,
@@ -16,11 +18,10 @@ type ResolveFunction = (
string,
ResolveContext,
ResolveFunction,
-) => Promise;
+) => Promise<{url: string}>;
type GetSourceContext = {
format: string,
- url: string,
};
type GetSourceFunction = (
@@ -29,14 +30,58 @@ type GetSourceFunction = (
GetSourceFunction,
) => Promise<{source: Source}>;
+type TransformSourceContext = {
+ format: string,
+ url: string,
+};
+
+type TransformSourceFunction = (
+ Source,
+ TransformSourceContext,
+ TransformSourceFunction,
+) => Promise<{source: Source}>;
+
type Source = string | ArrayBuffer | Uint8Array;
+let warnedAboutConditionsFlag = false;
+
+let stashedGetSource: null | GetSourceFunction = null;
+let stashedResolve: null | ResolveFunction = null;
+
export async function resolve(
specifier: string,
context: ResolveContext,
defaultResolve: ResolveFunction,
-): Promise {
- // TODO: Resolve server-only files.
+): Promise<{url: string}> {
+ // We stash this in case we end up needing to resolve export * statements later.
+ stashedResolve = defaultResolve;
+
+ if (!context.conditions.includes('react-server')) {
+ context = {
+ ...context,
+ conditions: [...context.conditions, 'react-server'],
+ };
+ if (!warnedAboutConditionsFlag) {
+ warnedAboutConditionsFlag = true;
+ // eslint-disable-next-line react-internal/no-production-logging
+ console.warn(
+ 'You did not run Node.js with the `--conditions react-server` flag. ' +
+ 'Any "react-server" override will only work with ESM imports.',
+ );
+ }
+ }
+ // We intentionally check the specifier here instead of the resolved file.
+ // This allows package exports to configure non-server aliases that resolve to server files
+ // depending on environment. It's probably a bad idea to export a server file as "main" though.
+ if (specifier.endsWith('.server.js')) {
+ if (context.parentURL && !context.parentURL.endsWith('.server.js')) {
+ throw new Error(
+ `Cannot import "${specifier}" from "${context.parentURL}". ` +
+ 'By react-server convention, .server.js files can only be imported from other .server.js files. ' +
+ 'That way nobody accidentally sends these to the client by indirectly importing it.',
+ );
+ }
+ }
return defaultResolve(specifier, context, defaultResolve);
}
@@ -44,14 +89,174 @@ export async function getSource(
url: string,
context: GetSourceContext,
defaultGetSource: GetSourceFunction,
+) {
+ // We stash this in case we end up needing to resolve export * statements later.
+ stashedGetSource = defaultGetSource;
+ return defaultGetSource(url, context, defaultGetSource);
+}
+
+function addExportNames(names, node) {
+ switch (node.type) {
+ case 'Identifier':
+ names.push(node.name);
+ return;
+ case 'ObjectPattern':
+ for (let i = 0; i < node.properties.length; i++)
+ addExportNames(names, node.properties[i]);
+ return;
+ case 'ArrayPattern':
+ for (let i = 0; i < node.elements.length; i++) {
+ const element = node.elements[i];
+ if (element) addExportNames(names, element);
+ }
+ return;
+ case 'Property':
+ addExportNames(names, node.value);
+ return;
+ case 'AssignmentPattern':
+ addExportNames(names, node.left);
+ return;
+ case 'RestElement':
+ addExportNames(names, node.argument);
+ return;
+ case 'ParenthesizedExpression':
+ addExportNames(names, node.expression);
+ return;
+ }
+}
+
+function resolveClientImport(
+ specifier: string,
+ parentURL: string,
+): Promise<{url: string}> {
+ // Resolve an import specifier as if it was loaded by the client. This doesn't use
+ // the overrides that this loader does but instead reverts to the default.
+ // This resolution algorithm will not necessarily have the same configuration
+ // as the actual client loader. It should mostly work and if it doesn't you can
+ // always convert to explicit exported names instead.
+ const conditions = ['node', 'import'];
+ if (stashedResolve === null) {
+ throw new Error(
+ 'Expected resolve to have been called before transformSource',
+ );
+ }
+ return stashedResolve(specifier, {conditions, parentURL}, stashedResolve);
+}
+
+async function loadClientImport(
+ url: string,
+ defaultTransformSource: TransformSourceFunction,
): Promise<{source: Source}> {
- if (url.endsWith('.client.js')) {
- // TODO: Named exports.
- const src =
- "export default { $$typeof: Symbol.for('react.module.reference'), name: " +
- JSON.stringify(url) +
- '}';
- return {source: src};
+ if (stashedGetSource === null) {
+ throw new Error(
+ 'Expected getSource to have been called before transformSource',
+ );
}
- return defaultGetSource(url, context, defaultGetSource);
+ // TODO: Validate that this is another module by calling getFormat.
+ const {source} = await stashedGetSource(
+ url,
+ {format: 'module'},
+ stashedGetSource,
+ );
+ return defaultTransformSource(
+ source,
+ {format: 'module', url},
+ defaultTransformSource,
+ );
+}
+
+async function parseExportNamesInto(
+ transformedSource: string,
+ names: Array,
+ parentURL: string,
+ defaultTransformSource,
+): Promise {
+ const {body} = acorn.parse(transformedSource, {
+ ecmaVersion: '2019',
+ sourceType: 'module',
+ });
+ for (let i = 0; i < body.length; i++) {
+ const node = body[i];
+ switch (node.type) {
+ case 'ExportAllDeclaration':
+ if (node.exported) {
+ addExportNames(names, node.exported);
+ continue;
+ } else {
+ const {url} = await resolveClientImport(node.source.value, parentURL);
+ const {source} = await loadClientImport(url, defaultTransformSource);
+ if (typeof source !== 'string') {
+ throw new Error('Expected the transformed source to be a string.');
+ }
+ parseExportNamesInto(source, names, url, defaultTransformSource);
+ continue;
+ }
+ case 'ExportDefaultDeclaration':
+ names.push('default');
+ continue;
+ case 'ExportNamedDeclaration':
+ if (node.declaration) {
+ if (node.declaration.type === 'VariableDeclaration') {
+ const declarations = node.declaration.declarations;
+ for (let j = 0; j < declarations.length; j++) {
+ addExportNames(names, declarations[j].id);
+ }
+ } else {
+ addExportNames(names, node.declaration.id);
+ }
+ }
+ if (node.specificers) {
+ const specificers = node.specificers;
+ for (let j = 0; j < specificers.length; j++) {
+ addExportNames(names, specificers[j].exported);
+ }
+ }
+ continue;
+ }
+ }
+}
+
+export async function transformSource(
+ source: Source,
+ context: TransformSourceContext,
+ defaultTransformSource: TransformSourceFunction,
+): Promise<{source: Source}> {
+ const transformed = await defaultTransformSource(
+ source,
+ context,
+ defaultTransformSource,
+ );
+ if (context.format === 'module' && context.url.endsWith('.client.js')) {
+ const transformedSource = transformed.source;
+ if (typeof transformedSource !== 'string') {
+ throw new Error('Expected source to have been transformed to a string.');
+ }
+
+ const names = [];
+ await parseExportNamesInto(
+ transformedSource,
+ names,
+ context.url,
+ defaultTransformSource,
+ );
+
+ let newSrc =
+ "const MODULE_REFERENCE = Symbol.for('react.module.reference');\n";
+ for (let i = 0; i < names.length; i++) {
+ const name = names[i];
+ if (name === 'default') {
+ newSrc += 'export default ';
+ } else {
+ newSrc += 'export const ' + name + ' = ';
+ }
+ newSrc += '{ $$typeof: MODULE_REFERENCE, filepath: ';
+ newSrc += JSON.stringify(context.url);
+ newSrc += ', name: ';
+ newSrc += JSON.stringify(name);
+ newSrc += '};\n';
+ }
+
+ return {source: newSrc};
+ }
+ return transformed;
}
diff --git a/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeRegister.js b/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeRegister.js
index f5149be1c42c4..26a92b8323d31 100644
--- a/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeRegister.js
+++ b/packages/react-transport-dom-webpack/src/ReactFlightWebpackNodeRegister.js
@@ -9,11 +9,83 @@
const url = require('url');
+// $FlowFixMe
+const Module = require('module');
+
module.exports = function register() {
+ const MODULE_REFERENCE = Symbol.for('react.module.reference');
+ const proxyHandlers = {
+ get: function(target, name, receiver) {
+ switch (name) {
+ // These names are read by the Flight runtime if you end up using the exports object.
+ case '$$typeof':
+ // These names are a little too common. We should probably have a way to
+ // have the Flight runtime extract the inner target instead.
+ return target.$$typeof;
+ case 'filepath':
+ return target.filepath;
+ case 'name':
+ return target.name;
+ // We need to special case this because createElement reads it if we pass this
+ // reference.
+ case 'defaultProps':
+ return undefined;
+ case '__esModule':
+ // Something is conditionally checking which export to use. We'll pretend to be
+ // an ESM compat module but then we'll check again on the client.
+ target.default = {
+ $$typeof: MODULE_REFERENCE,
+ filepath: target.filepath,
+ // This a placeholder value that tells the client to conditionally use the
+ // whole object or just the default export.
+ name: '',
+ };
+ return true;
+ }
+ let cachedReference = target[name];
+ if (!cachedReference) {
+ cachedReference = target[name] = {
+ $$typeof: MODULE_REFERENCE,
+ filepath: target.filepath,
+ name: name,
+ };
+ }
+ return cachedReference;
+ },
+ set: function() {
+ throw new Error('Cannot assign to a client module from a server module.');
+ },
+ };
+
(require: any).extensions['.client.js'] = function(module, path) {
- module.exports = {
- $$typeof: Symbol.for('react.module.reference'),
- name: url.pathToFileURL(path).href,
+ const moduleId = url.pathToFileURL(path).href;
+ const moduleReference: {[string]: any} = {
+ $$typeof: MODULE_REFERENCE,
+ filepath: moduleId,
+ name: '*', // Represents the whole object instead of a particular import.
};
+ module.exports = new Proxy(moduleReference, proxyHandlers);
+ };
+
+ const originalResolveFilename = Module._resolveFilename;
+
+ Module._resolveFilename = function(request, parent, isMain, options) {
+ // We intentionally check the request here instead of the resolved file.
+ // This allows package exports to configure non-server aliases that resolve to server files
+ // depending on environment. It's probably a bad idea to export a server file as "main" though.
+ if (request.endsWith('.server.js')) {
+ if (
+ parent &&
+ parent.filename &&
+ !parent.filename.endsWith('.server.js')
+ ) {
+ throw new Error(
+ `Cannot import "${request}" from "${parent.filename}". ` +
+ 'By react-server convention, .server.js files can only be imported from other .server.js files. ' +
+ 'That way nobody accidentally sends these to the client by indirectly importing it.',
+ );
+ }
+ }
+ return originalResolveFilename.apply(this, arguments);
};
};
diff --git a/packages/react-transport-dom-webpack/src/__tests__/ReactFlightDOM-test.js b/packages/react-transport-dom-webpack/src/__tests__/ReactFlightDOM-test.js
index d8568c661c2af..e437c7b20bc61 100644
--- a/packages/react-transport-dom-webpack/src/__tests__/ReactFlightDOM-test.js
+++ b/packages/react-transport-dom-webpack/src/__tests__/ReactFlightDOM-test.js
@@ -68,12 +68,14 @@ describe('ReactFlightDOM', () => {
d: moduleExport,
};
webpackMap['path/' + idx] = {
- id: '' + idx,
- chunks: [],
- name: 'd',
+ default: {
+ id: '' + idx,
+ chunks: [],
+ name: 'd',
+ },
};
const MODULE_TAG = Symbol.for('react.module.reference');
- return {$$typeof: MODULE_TAG, name: 'path/' + idx};
+ return {$$typeof: MODULE_TAG, filepath: 'path/' + idx, name: 'default'};
}
async function waitForSuspense(fn) {
diff --git a/scripts/flow/environment.js b/scripts/flow/environment.js
index 8fd7111ebf521..3efe41ff344d2 100644
--- a/scripts/flow/environment.js
+++ b/scripts/flow/environment.js
@@ -68,4 +68,4 @@ declare module 'EventListener' {
}
declare function __webpack_chunk_load__(id: string): Promise;
-declare function __webpack_require__(id: string): {default: any};
+declare function __webpack_require__(id: string): any;
diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js
index f39d197eb0363..6f0f88e04e00b 100644
--- a/scripts/rollup/bundles.js
+++ b/scripts/rollup/bundles.js
@@ -301,7 +301,7 @@ const bundles = [
moduleType: RENDERER_UTILS,
entry: 'react-transport-dom-webpack/node-loader',
global: 'ReactFlightWebpackNodeLoader',
- externals: [],
+ externals: ['acorn'],
},
/******* React Transport DOM Webpack Node.js CommonJS Loader *******/
@@ -310,7 +310,7 @@ const bundles = [
moduleType: RENDERER_UTILS,
entry: 'react-transport-dom-webpack/node-register',
global: 'ReactFlightWebpackNodeRegister',
- externals: ['url'],
+ externals: ['url', 'module'],
},
/******* React Transport DOM Server Relay *******/
diff --git a/yarn.lock b/yarn.lock
index d44e85f4e47d7..7b6cb08909628 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2617,15 +2617,10 @@ acorn-globals@^6.0.0:
acorn "^7.1.1"
acorn-walk "^7.1.1"
-acorn-jsx@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384"
- integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==
-
-acorn-jsx@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
- integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
+acorn-jsx@^5.0.0, acorn-jsx@^5.2.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
+ integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
acorn-walk@^6.0.1:
version "6.2.0"
@@ -2637,25 +2632,15 @@ acorn-walk@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn@^6.0.1, acorn@^6.0.7:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e"
- integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==
-
-acorn@^6.4.1:
- version "6.4.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
- integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
-
-acorn@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c"
- integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==
+acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.1, acorn@^6.4.1:
+ version "6.4.2"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
+ integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
-acorn@^7.1.1, acorn@^7.4.0:
- version "7.4.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
- integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
+acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+ integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
adbkit-logcat@^1.1.0:
version "1.1.0"