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 os = require('os');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const toLocalPath = require('../node-haste/lib/toLocalPath');
|
||||
|
||||
const {generateAssetTransformResult, isAssetTypeAnImage} = require('./util');
|
||||
|
||||
const {
|
||||
sep: pathSeparator,
|
||||
join: joinPath,
|
||||
relative: relativePath,
|
||||
dirname: pathDirname,
|
||||
extname,
|
||||
} = 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) {
|
||||
// Verify that the root exists.
|
||||
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');
|
||||
|
||||
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';
|
||||
|
||||
export type TransformedCode = {
|
||||
|
|
|
@ -18,6 +18,7 @@ const FetchError = require('node-fetch/lib/fetch-error');
|
|||
|
||||
const crypto = require('crypto');
|
||||
const fetch = require('node-fetch');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const jsonStableStringify = require('json-stable-stringify');
|
||||
const path = require('path');
|
||||
const throat = require('throat');
|
||||
|
@ -26,6 +27,7 @@ import type {
|
|||
Options as TransformWorkerOptions,
|
||||
TransformOptionsStrict,
|
||||
} from '../JSTransformer/worker/worker';
|
||||
import type {LocalPath} from '../node-haste/lib/toLocalPath';
|
||||
import type {CachedResult, GetTransformCacheKey} from './TransformCache';
|
||||
|
||||
/**
|
||||
|
@ -62,10 +64,10 @@ type FetchResultFromURI = (uri: string) => Promise<?CachedResult>;
|
|||
type StoreResults = (resultsByKey: Map<string, CachedResult>) => Promise<void>;
|
||||
|
||||
export type FetchProps = {
|
||||
filePath: string,
|
||||
sourceCode: string,
|
||||
getTransformCacheKey: GetTransformCacheKey,
|
||||
transformOptions: TransformWorkerOptions,
|
||||
+localPath: LocalPath,
|
||||
+sourceCode: string,
|
||||
+getTransformCacheKey: GetTransformCacheKey,
|
||||
+transformOptions: TransformWorkerOptions,
|
||||
};
|
||||
|
||||
type URI = string;
|
||||
|
@ -227,13 +229,13 @@ class URIBasedGlobalTransformCache {
|
|||
*/
|
||||
keyOf(props: FetchProps) {
|
||||
const hash = crypto.createHash('sha1');
|
||||
const {sourceCode, filePath, transformOptions} = props;
|
||||
const {sourceCode, localPath, transformOptions} = props;
|
||||
hash.update(this._optionsHasher.getTransformWorkerOptionsDigest(transformOptions));
|
||||
const cacheKey = props.getTransformCacheKey(transformOptions);
|
||||
hash.update(JSON.stringify(cacheKey));
|
||||
hash.update(crypto.createHash('sha1').update(sourceCode).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 {MappingsMap} from './SourceMap';
|
||||
import type {Reporter} from './reporting';
|
||||
import type {LocalPath} from '../node-haste/lib/toLocalPath';
|
||||
|
||||
type CacheFilePaths = {transformedCode: string, metadata: string};
|
||||
export type GetTransformCacheKey = (options: {}) => string;
|
||||
|
@ -50,6 +51,7 @@ export type CacheOptions = {
|
|||
|
||||
export type ReadTransformProps = {
|
||||
filePath: string,
|
||||
localPath: LocalPath,
|
||||
sourceCode: string,
|
||||
transformOptions: WorkerOptions,
|
||||
transformOptionsKey: string,
|
||||
|
|
|
@ -55,12 +55,12 @@ describe('GlobalTransformCache', () => {
|
|||
},
|
||||
};
|
||||
const result = await Promise.all([cache.fetch({
|
||||
filePath: 'foo.js',
|
||||
localPath: 'some/where/foo.js',
|
||||
sourceCode: '/* beep */',
|
||||
getTransformCacheKey: () => 'abcd',
|
||||
transformOptions,
|
||||
}), cache.fetch({
|
||||
filePath: 'bar.js',
|
||||
localPath: 'some/where/else/bar.js',
|
||||
sourceCode: '/* boop */',
|
||||
getTransformCacheKey: () => 'abcd',
|
||||
transformOptions,
|
||||
|
|
|
@ -19,12 +19,12 @@ Object {
|
|||
exports[`GlobalTransformCache fetches results 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"code": "/* code from http://globalcache.com/cd6df9b7e86839dafc5e9b5b493a28cbc55074e7-foo.js */",
|
||||
"code": "/* code from http://globalcache.com/cd6df9b7e86839dafc5e9b5b493a28cbc55074e7-some/where/foo.js */",
|
||||
"dependencies": Array [],
|
||||
"dependencyOffsets": Array [],
|
||||
},
|
||||
Object {
|
||||
"code": "/* code from http://globalcache.com/6329a317fcf94d74cc9a1de6442ee7c25e27a507-bar.js */",
|
||||
"code": "/* code from http://globalcache.com/6329a317fcf94d74cc9a1de6442ee7c25e27a507-some/where/else/bar.js */",
|
||||
"dependencies": Array [],
|
||||
"dependencyOffsets": Array [],
|
||||
},
|
||||
|
|
|
@ -162,14 +162,15 @@ class DependencyGraph extends EventEmitter {
|
|||
_createModuleCache() {
|
||||
const {_opts} = this;
|
||||
return new ModuleCache({
|
||||
assetDependencies: _opts.assetDependencies,
|
||||
depGraphHelpers: this._helpers,
|
||||
getClosestPackage: this._getClosestPackage.bind(this),
|
||||
getTransformCacheKey: _opts.getTransformCacheKey,
|
||||
globalTransformCache: _opts.globalTransformCache,
|
||||
transformCode: _opts.transformCode,
|
||||
depGraphHelpers: this._helpers,
|
||||
assetDependencies: _opts.assetDependencies,
|
||||
moduleOptions: _opts.moduleOptions,
|
||||
reporter: _opts.reporter,
|
||||
getClosestPackage: this._getClosestPackage.bind(this),
|
||||
roots: _opts.roots,
|
||||
transformCode: _opts.transformCode,
|
||||
}, _opts.platforms);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import type {Reporter} from '../lib/reporting';
|
|||
import type DependencyGraphHelpers
|
||||
from './DependencyGraph/DependencyGraphHelpers';
|
||||
import type ModuleCache from './ModuleCache';
|
||||
import type {LocalPath} from './lib/toLocalPath';
|
||||
|
||||
export type ReadResult = {
|
||||
+code: string,
|
||||
|
@ -74,6 +75,7 @@ export type ConstructorArgs = {
|
|||
depGraphHelpers: DependencyGraphHelpers,
|
||||
globalTransformCache: ?GlobalTransformCache,
|
||||
file: string,
|
||||
localPath: LocalPath,
|
||||
moduleCache: ModuleCache,
|
||||
options: Options,
|
||||
reporter: Reporter,
|
||||
|
@ -86,6 +88,7 @@ type DocBlock = {+[key: string]: string};
|
|||
const TRANSFORM_CACHE = new TransformCache();
|
||||
|
||||
class Module {
|
||||
localPath: LocalPath;
|
||||
path: string;
|
||||
type: string;
|
||||
|
||||
|
@ -106,6 +109,7 @@ class Module {
|
|||
|
||||
constructor({
|
||||
depGraphHelpers,
|
||||
localPath,
|
||||
file,
|
||||
getTransformCacheKey,
|
||||
globalTransformCache,
|
||||
|
@ -118,6 +122,7 @@ class Module {
|
|||
throw new Error('Expected file to be absolute path but got ' + file);
|
||||
}
|
||||
|
||||
this.localPath = localPath;
|
||||
this.path = file;
|
||||
this.type = 'Module';
|
||||
|
||||
|
@ -436,6 +441,7 @@ class Module {
|
|||
const getTransformCacheKey = this._getTransformCacheKey;
|
||||
return {
|
||||
filePath: this.path,
|
||||
localPath: this.localPath,
|
||||
sourceCode,
|
||||
getTransformCacheKey,
|
||||
transformOptions,
|
||||
|
|
|
@ -17,6 +17,8 @@ const Module = require('./Module');
|
|||
const Package = require('./Package');
|
||||
const Polyfill = require('./Polyfill');
|
||||
|
||||
const toLocalPath = require('./lib/toLocalPath');
|
||||
|
||||
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
|
||||
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
||||
import type {Reporter} from '../lib/reporting';
|
||||
|
@ -39,6 +41,7 @@ class ModuleCache {
|
|||
_platforms: Set<string>;
|
||||
_transformCode: TransformCode;
|
||||
_reporter: Reporter;
|
||||
_roots: Array<string>;
|
||||
|
||||
constructor(
|
||||
{
|
||||
|
@ -49,18 +52,20 @@ class ModuleCache {
|
|||
getTransformCacheKey,
|
||||
globalTransformCache,
|
||||
moduleOptions,
|
||||
roots,
|
||||
reporter,
|
||||
transformCode,
|
||||
}: {
|
||||
}: {|
|
||||
assetDependencies: Array<string>,
|
||||
depGraphHelpers: DependencyGraphHelpers,
|
||||
getClosestPackage: GetClosestPackageFn,
|
||||
getTransformCacheKey: GetTransformCacheKey,
|
||||
globalTransformCache: ?GlobalTransformCache,
|
||||
moduleOptions: ModuleOptions,
|
||||
roots: Array<string>,
|
||||
reporter: Reporter,
|
||||
transformCode: TransformCode,
|
||||
},
|
||||
|},
|
||||
platforms: Set<string>,
|
||||
) {
|
||||
this._assetDependencies = assetDependencies;
|
||||
|
@ -75,6 +80,7 @@ class ModuleCache {
|
|||
this._platforms = platforms;
|
||||
this._transformCode = transformCode;
|
||||
this._reporter = reporter;
|
||||
this._roots = roots;
|
||||
}
|
||||
|
||||
getModule(filePath: string): Module {
|
||||
|
@ -84,6 +90,7 @@ class ModuleCache {
|
|||
file: filePath,
|
||||
getTransformCacheKey: this._getTransformCacheKey,
|
||||
globalTransformCache: this._globalTransformCache,
|
||||
localPath: toLocalPath(this._roots, filePath),
|
||||
moduleCache: this,
|
||||
options: this._moduleOptions,
|
||||
reporter: this._reporter,
|
||||
|
@ -99,14 +106,22 @@ class ModuleCache {
|
|||
|
||||
getAssetModule(filePath: string) {
|
||||
if (!this._moduleCache[filePath]) {
|
||||
/* $FlowFixMe: missing options. This is because this is an incorrect OOP
|
||||
* design in the first place: AssetModule, being simpler than a normal
|
||||
* Module, should not inherit the Module class. */
|
||||
/* FixMe: AssetModule does not need all these options. This is because
|
||||
* this is an incorrect OOP design in the first place: AssetModule, being
|
||||
* simpler than a normal Module, should not inherit the Module class.
|
||||
*/
|
||||
this._moduleCache[filePath] = new AssetModule(
|
||||
{
|
||||
file: filePath,
|
||||
moduleCache: this,
|
||||
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,
|
||||
);
|
||||
|
@ -149,6 +164,7 @@ class ModuleCache {
|
|||
file,
|
||||
depGraphHelpers: this._depGraphHelpers,
|
||||
getTransformCacheKey: this._getTransformCacheKey,
|
||||
localPath: toLocalPath(this._roots, file),
|
||||
moduleCache: this,
|
||||
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