mirror of https://github.com/status-im/metro.git
Use local paths for global cache
Summary: Changes the global cache to use *local paths* rather than base names of files for the cache key. This is to enable correct usage of babel transforms like `transform-react-jsx-source` that use file paths in their output. It remains a responsibility of the transform implementer to pass relative paths to babel if the global cache is being used. Reviewed By: jeanlauliac Differential Revision: D5044028 fbshipit-source-id: 2ef1e1545e510a18ab49a307053d91b4f40269b2
This commit is contained in:
parent
497d3ff228
commit
6ecfa15780
|
@ -26,13 +26,13 @@ const denodeify = require('denodeify');
|
||||||
const defaults = require('../../defaults');
|
const defaults = require('../../defaults');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
|
const toLocalPath = require('../node-haste/lib/toLocalPath');
|
||||||
|
|
||||||
const {generateAssetTransformResult, isAssetTypeAnImage} = require('./util');
|
const {generateAssetTransformResult, isAssetTypeAnImage} = require('./util');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
sep: pathSeparator,
|
sep: pathSeparator,
|
||||||
join: joinPath,
|
join: joinPath,
|
||||||
relative: relativePath,
|
|
||||||
dirname: pathDirname,
|
dirname: pathDirname,
|
||||||
extname,
|
extname,
|
||||||
} = require('path');
|
} = require('path');
|
||||||
|
@ -842,19 +842,6 @@ class Bundler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toLocalPath(roots, absPath) {
|
|
||||||
for (let i = 0; i < roots.length; i++) {
|
|
||||||
const localPath = relativePath(roots[i], absPath);
|
|
||||||
if (localPath[0] !== '.') {
|
|
||||||
return localPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(
|
|
||||||
'Expected root module to be relative to one of the project roots'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function verifyRootExists(root) {
|
function verifyRootExists(root) {
|
||||||
// Verify that the root exists.
|
// Verify that the root exists.
|
||||||
assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory');
|
assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory');
|
||||||
|
|
|
@ -19,6 +19,7 @@ const invariant = require('fbjs/lib/invariant');
|
||||||
const minify = require('./minify');
|
const minify = require('./minify');
|
||||||
|
|
||||||
import type {LogEntry} from '../../Logger/Types';
|
import type {LogEntry} from '../../Logger/Types';
|
||||||
|
import type {LocalPath} from '../../node-haste/lib/toLocalPath';
|
||||||
import type {Ast, Plugins as BabelPlugins, SourceMap as MappingsMap} from 'babel-core';
|
import type {Ast, Plugins as BabelPlugins, SourceMap as MappingsMap} from 'babel-core';
|
||||||
|
|
||||||
export type TransformedCode = {
|
export type TransformedCode = {
|
||||||
|
|
|
@ -18,6 +18,7 @@ const FetchError = require('node-fetch/lib/fetch-error');
|
||||||
|
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
|
const invariant = require('fbjs/lib/invariant');
|
||||||
const jsonStableStringify = require('json-stable-stringify');
|
const jsonStableStringify = require('json-stable-stringify');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const throat = require('throat');
|
const throat = require('throat');
|
||||||
|
@ -26,6 +27,7 @@ import type {
|
||||||
Options as TransformWorkerOptions,
|
Options as TransformWorkerOptions,
|
||||||
TransformOptionsStrict,
|
TransformOptionsStrict,
|
||||||
} from '../JSTransformer/worker/worker';
|
} from '../JSTransformer/worker/worker';
|
||||||
|
import type {LocalPath} from '../node-haste/lib/toLocalPath';
|
||||||
import type {CachedResult, GetTransformCacheKey} from './TransformCache';
|
import type {CachedResult, GetTransformCacheKey} from './TransformCache';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,10 +64,10 @@ type FetchResultFromURI = (uri: string) => Promise<?CachedResult>;
|
||||||
type StoreResults = (resultsByKey: Map<string, CachedResult>) => Promise<void>;
|
type StoreResults = (resultsByKey: Map<string, CachedResult>) => Promise<void>;
|
||||||
|
|
||||||
export type FetchProps = {
|
export type FetchProps = {
|
||||||
filePath: string,
|
+localPath: LocalPath,
|
||||||
sourceCode: string,
|
+sourceCode: string,
|
||||||
getTransformCacheKey: GetTransformCacheKey,
|
+getTransformCacheKey: GetTransformCacheKey,
|
||||||
transformOptions: TransformWorkerOptions,
|
+transformOptions: TransformWorkerOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
type URI = string;
|
type URI = string;
|
||||||
|
@ -227,13 +229,13 @@ class URIBasedGlobalTransformCache {
|
||||||
*/
|
*/
|
||||||
keyOf(props: FetchProps) {
|
keyOf(props: FetchProps) {
|
||||||
const hash = crypto.createHash('sha1');
|
const hash = crypto.createHash('sha1');
|
||||||
const {sourceCode, filePath, transformOptions} = props;
|
const {sourceCode, localPath, transformOptions} = props;
|
||||||
hash.update(this._optionsHasher.getTransformWorkerOptionsDigest(transformOptions));
|
hash.update(this._optionsHasher.getTransformWorkerOptionsDigest(transformOptions));
|
||||||
const cacheKey = props.getTransformCacheKey(transformOptions);
|
const cacheKey = props.getTransformCacheKey(transformOptions);
|
||||||
hash.update(JSON.stringify(cacheKey));
|
hash.update(JSON.stringify(cacheKey));
|
||||||
hash.update(crypto.createHash('sha1').update(sourceCode).digest('hex'));
|
hash.update(crypto.createHash('sha1').update(sourceCode).digest('hex'));
|
||||||
const digest = hash.digest('hex');
|
const digest = hash.digest('hex');
|
||||||
return `${digest}-${path.basename(filePath)}`;
|
return `${digest}-${localPath}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,6 +24,7 @@ const writeFileAtomicSync = require('write-file-atomic').sync;
|
||||||
import type {Options as WorkerOptions} from '../JSTransformer/worker/worker';
|
import type {Options as WorkerOptions} from '../JSTransformer/worker/worker';
|
||||||
import type {MappingsMap} from './SourceMap';
|
import type {MappingsMap} from './SourceMap';
|
||||||
import type {Reporter} from './reporting';
|
import type {Reporter} from './reporting';
|
||||||
|
import type {LocalPath} from '../node-haste/lib/toLocalPath';
|
||||||
|
|
||||||
type CacheFilePaths = {transformedCode: string, metadata: string};
|
type CacheFilePaths = {transformedCode: string, metadata: string};
|
||||||
export type GetTransformCacheKey = (options: {}) => string;
|
export type GetTransformCacheKey = (options: {}) => string;
|
||||||
|
@ -50,6 +51,7 @@ export type CacheOptions = {
|
||||||
|
|
||||||
export type ReadTransformProps = {
|
export type ReadTransformProps = {
|
||||||
filePath: string,
|
filePath: string,
|
||||||
|
localPath: LocalPath,
|
||||||
sourceCode: string,
|
sourceCode: string,
|
||||||
transformOptions: WorkerOptions,
|
transformOptions: WorkerOptions,
|
||||||
transformOptionsKey: string,
|
transformOptionsKey: string,
|
||||||
|
|
|
@ -55,12 +55,12 @@ describe('GlobalTransformCache', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const result = await Promise.all([cache.fetch({
|
const result = await Promise.all([cache.fetch({
|
||||||
filePath: 'foo.js',
|
localPath: 'some/where/foo.js',
|
||||||
sourceCode: '/* beep */',
|
sourceCode: '/* beep */',
|
||||||
getTransformCacheKey: () => 'abcd',
|
getTransformCacheKey: () => 'abcd',
|
||||||
transformOptions,
|
transformOptions,
|
||||||
}), cache.fetch({
|
}), cache.fetch({
|
||||||
filePath: 'bar.js',
|
localPath: 'some/where/else/bar.js',
|
||||||
sourceCode: '/* boop */',
|
sourceCode: '/* boop */',
|
||||||
getTransformCacheKey: () => 'abcd',
|
getTransformCacheKey: () => 'abcd',
|
||||||
transformOptions,
|
transformOptions,
|
||||||
|
|
|
@ -19,12 +19,12 @@ Object {
|
||||||
exports[`GlobalTransformCache fetches results 1`] = `
|
exports[`GlobalTransformCache fetches results 1`] = `
|
||||||
Array [
|
Array [
|
||||||
Object {
|
Object {
|
||||||
"code": "/* code from http://globalcache.com/cd6df9b7e86839dafc5e9b5b493a28cbc55074e7-foo.js */",
|
"code": "/* code from http://globalcache.com/cd6df9b7e86839dafc5e9b5b493a28cbc55074e7-some/where/foo.js */",
|
||||||
"dependencies": Array [],
|
"dependencies": Array [],
|
||||||
"dependencyOffsets": Array [],
|
"dependencyOffsets": Array [],
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"code": "/* code from http://globalcache.com/6329a317fcf94d74cc9a1de6442ee7c25e27a507-bar.js */",
|
"code": "/* code from http://globalcache.com/6329a317fcf94d74cc9a1de6442ee7c25e27a507-some/where/else/bar.js */",
|
||||||
"dependencies": Array [],
|
"dependencies": Array [],
|
||||||
"dependencyOffsets": Array [],
|
"dependencyOffsets": Array [],
|
||||||
},
|
},
|
||||||
|
|
|
@ -162,14 +162,15 @@ class DependencyGraph extends EventEmitter {
|
||||||
_createModuleCache() {
|
_createModuleCache() {
|
||||||
const {_opts} = this;
|
const {_opts} = this;
|
||||||
return new ModuleCache({
|
return new ModuleCache({
|
||||||
|
assetDependencies: _opts.assetDependencies,
|
||||||
|
depGraphHelpers: this._helpers,
|
||||||
|
getClosestPackage: this._getClosestPackage.bind(this),
|
||||||
getTransformCacheKey: _opts.getTransformCacheKey,
|
getTransformCacheKey: _opts.getTransformCacheKey,
|
||||||
globalTransformCache: _opts.globalTransformCache,
|
globalTransformCache: _opts.globalTransformCache,
|
||||||
transformCode: _opts.transformCode,
|
|
||||||
depGraphHelpers: this._helpers,
|
|
||||||
assetDependencies: _opts.assetDependencies,
|
|
||||||
moduleOptions: _opts.moduleOptions,
|
moduleOptions: _opts.moduleOptions,
|
||||||
reporter: _opts.reporter,
|
reporter: _opts.reporter,
|
||||||
getClosestPackage: this._getClosestPackage.bind(this),
|
roots: _opts.roots,
|
||||||
|
transformCode: _opts.transformCode,
|
||||||
}, _opts.platforms);
|
}, _opts.platforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import type {Reporter} from '../lib/reporting';
|
||||||
import type DependencyGraphHelpers
|
import type DependencyGraphHelpers
|
||||||
from './DependencyGraph/DependencyGraphHelpers';
|
from './DependencyGraph/DependencyGraphHelpers';
|
||||||
import type ModuleCache from './ModuleCache';
|
import type ModuleCache from './ModuleCache';
|
||||||
|
import type {LocalPath} from './lib/toLocalPath';
|
||||||
|
|
||||||
export type ReadResult = {
|
export type ReadResult = {
|
||||||
+code: string,
|
+code: string,
|
||||||
|
@ -74,6 +75,7 @@ export type ConstructorArgs = {
|
||||||
depGraphHelpers: DependencyGraphHelpers,
|
depGraphHelpers: DependencyGraphHelpers,
|
||||||
globalTransformCache: ?GlobalTransformCache,
|
globalTransformCache: ?GlobalTransformCache,
|
||||||
file: string,
|
file: string,
|
||||||
|
localPath: LocalPath,
|
||||||
moduleCache: ModuleCache,
|
moduleCache: ModuleCache,
|
||||||
options: Options,
|
options: Options,
|
||||||
reporter: Reporter,
|
reporter: Reporter,
|
||||||
|
@ -86,6 +88,7 @@ type DocBlock = {+[key: string]: string};
|
||||||
const TRANSFORM_CACHE = new TransformCache();
|
const TRANSFORM_CACHE = new TransformCache();
|
||||||
|
|
||||||
class Module {
|
class Module {
|
||||||
|
localPath: LocalPath;
|
||||||
path: string;
|
path: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
|
||||||
|
@ -106,6 +109,7 @@ class Module {
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
depGraphHelpers,
|
depGraphHelpers,
|
||||||
|
localPath,
|
||||||
file,
|
file,
|
||||||
getTransformCacheKey,
|
getTransformCacheKey,
|
||||||
globalTransformCache,
|
globalTransformCache,
|
||||||
|
@ -118,6 +122,7 @@ class Module {
|
||||||
throw new Error('Expected file to be absolute path but got ' + file);
|
throw new Error('Expected file to be absolute path but got ' + file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.localPath = localPath;
|
||||||
this.path = file;
|
this.path = file;
|
||||||
this.type = 'Module';
|
this.type = 'Module';
|
||||||
|
|
||||||
|
@ -436,6 +441,7 @@ class Module {
|
||||||
const getTransformCacheKey = this._getTransformCacheKey;
|
const getTransformCacheKey = this._getTransformCacheKey;
|
||||||
return {
|
return {
|
||||||
filePath: this.path,
|
filePath: this.path,
|
||||||
|
localPath: this.localPath,
|
||||||
sourceCode,
|
sourceCode,
|
||||||
getTransformCacheKey,
|
getTransformCacheKey,
|
||||||
transformOptions,
|
transformOptions,
|
||||||
|
|
|
@ -17,6 +17,8 @@ const Module = require('./Module');
|
||||||
const Package = require('./Package');
|
const Package = require('./Package');
|
||||||
const Polyfill = require('./Polyfill');
|
const Polyfill = require('./Polyfill');
|
||||||
|
|
||||||
|
const toLocalPath = require('./lib/toLocalPath');
|
||||||
|
|
||||||
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
|
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
|
||||||
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
||||||
import type {Reporter} from '../lib/reporting';
|
import type {Reporter} from '../lib/reporting';
|
||||||
|
@ -39,6 +41,7 @@ class ModuleCache {
|
||||||
_platforms: Set<string>;
|
_platforms: Set<string>;
|
||||||
_transformCode: TransformCode;
|
_transformCode: TransformCode;
|
||||||
_reporter: Reporter;
|
_reporter: Reporter;
|
||||||
|
_roots: Array<string>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{
|
{
|
||||||
|
@ -49,18 +52,20 @@ class ModuleCache {
|
||||||
getTransformCacheKey,
|
getTransformCacheKey,
|
||||||
globalTransformCache,
|
globalTransformCache,
|
||||||
moduleOptions,
|
moduleOptions,
|
||||||
|
roots,
|
||||||
reporter,
|
reporter,
|
||||||
transformCode,
|
transformCode,
|
||||||
}: {
|
}: {|
|
||||||
assetDependencies: Array<string>,
|
assetDependencies: Array<string>,
|
||||||
depGraphHelpers: DependencyGraphHelpers,
|
depGraphHelpers: DependencyGraphHelpers,
|
||||||
getClosestPackage: GetClosestPackageFn,
|
getClosestPackage: GetClosestPackageFn,
|
||||||
getTransformCacheKey: GetTransformCacheKey,
|
getTransformCacheKey: GetTransformCacheKey,
|
||||||
globalTransformCache: ?GlobalTransformCache,
|
globalTransformCache: ?GlobalTransformCache,
|
||||||
moduleOptions: ModuleOptions,
|
moduleOptions: ModuleOptions,
|
||||||
|
roots: Array<string>,
|
||||||
reporter: Reporter,
|
reporter: Reporter,
|
||||||
transformCode: TransformCode,
|
transformCode: TransformCode,
|
||||||
},
|
|},
|
||||||
platforms: Set<string>,
|
platforms: Set<string>,
|
||||||
) {
|
) {
|
||||||
this._assetDependencies = assetDependencies;
|
this._assetDependencies = assetDependencies;
|
||||||
|
@ -75,6 +80,7 @@ class ModuleCache {
|
||||||
this._platforms = platforms;
|
this._platforms = platforms;
|
||||||
this._transformCode = transformCode;
|
this._transformCode = transformCode;
|
||||||
this._reporter = reporter;
|
this._reporter = reporter;
|
||||||
|
this._roots = roots;
|
||||||
}
|
}
|
||||||
|
|
||||||
getModule(filePath: string): Module {
|
getModule(filePath: string): Module {
|
||||||
|
@ -84,6 +90,7 @@ class ModuleCache {
|
||||||
file: filePath,
|
file: filePath,
|
||||||
getTransformCacheKey: this._getTransformCacheKey,
|
getTransformCacheKey: this._getTransformCacheKey,
|
||||||
globalTransformCache: this._globalTransformCache,
|
globalTransformCache: this._globalTransformCache,
|
||||||
|
localPath: toLocalPath(this._roots, filePath),
|
||||||
moduleCache: this,
|
moduleCache: this,
|
||||||
options: this._moduleOptions,
|
options: this._moduleOptions,
|
||||||
reporter: this._reporter,
|
reporter: this._reporter,
|
||||||
|
@ -99,14 +106,22 @@ class ModuleCache {
|
||||||
|
|
||||||
getAssetModule(filePath: string) {
|
getAssetModule(filePath: string) {
|
||||||
if (!this._moduleCache[filePath]) {
|
if (!this._moduleCache[filePath]) {
|
||||||
/* $FlowFixMe: missing options. This is because this is an incorrect OOP
|
/* FixMe: AssetModule does not need all these options. This is because
|
||||||
* design in the first place: AssetModule, being simpler than a normal
|
* this is an incorrect OOP design in the first place: AssetModule, being
|
||||||
* Module, should not inherit the Module class. */
|
* simpler than a normal Module, should not inherit the Module class.
|
||||||
|
*/
|
||||||
this._moduleCache[filePath] = new AssetModule(
|
this._moduleCache[filePath] = new AssetModule(
|
||||||
{
|
{
|
||||||
file: filePath,
|
|
||||||
moduleCache: this,
|
|
||||||
dependencies: this._assetDependencies,
|
dependencies: this._assetDependencies,
|
||||||
|
depGraphHelpers: this._depGraphHelpers,
|
||||||
|
file: filePath,
|
||||||
|
getTransformCacheKey: this._getTransformCacheKey,
|
||||||
|
globalTransformCache: null,
|
||||||
|
localPath: toLocalPath(this._roots, filePath),
|
||||||
|
moduleCache: this,
|
||||||
|
options: this._moduleOptions,
|
||||||
|
reporter: this._reporter,
|
||||||
|
transformCode: this._transformCode,
|
||||||
},
|
},
|
||||||
this._platforms,
|
this._platforms,
|
||||||
);
|
);
|
||||||
|
@ -149,6 +164,7 @@ class ModuleCache {
|
||||||
file,
|
file,
|
||||||
depGraphHelpers: this._depGraphHelpers,
|
depGraphHelpers: this._depGraphHelpers,
|
||||||
getTransformCacheKey: this._getTransformCacheKey,
|
getTransformCacheKey: this._getTransformCacheKey,
|
||||||
|
localPath: toLocalPath(this._roots, file),
|
||||||
moduleCache: this,
|
moduleCache: this,
|
||||||
transformCode: this._transformCode,
|
transformCode: this._transformCode,
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const {relative} = require('path');
|
||||||
|
|
||||||
|
declare class OpaqueLocalPath {}
|
||||||
|
export type LocalPath = OpaqueLocalPath & string;
|
||||||
|
|
||||||
|
// FIXME: This function has the shortcoming of potentially returning identical
|
||||||
|
// paths for two files in different roots.
|
||||||
|
function toLocalPath(roots: Array<string>, absolutePath: string): LocalPath {
|
||||||
|
for (let i = 0; i < roots.length; i++) {
|
||||||
|
const localPath = relative(roots[i], absolutePath);
|
||||||
|
if (localPath[0] !== '.') {
|
||||||
|
return (localPath: any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
'Expected root module to be relative to one of the project roots'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = toLocalPath;
|
Loading…
Reference in New Issue