diff --git a/packages/metro-bundler/src/Bundler/index.js b/packages/metro-bundler/src/Bundler/index.js index 8f4832be..b496eaae 100644 --- a/packages/metro-bundler/src/Bundler/index.js +++ b/packages/metro-bundler/src/Bundler/index.js @@ -124,11 +124,12 @@ class Bundler { this._getModuleId = createModuleIdFactory(); + let getCacheKey = () => ''; if (opts.transformModulePath) { /* $FlowFixMe: dynamic requires prevent static typing :'( */ const transformer = require(opts.transformModulePath); - if (typeof transformer.cacheKey !== 'undefined') { - cacheKeyParts.push(transformer.cacheKey); + if (typeof transformer.getCacheKey !== 'undefined') { + getCacheKey = transformer.getCacheKey; } } @@ -146,11 +147,16 @@ class Bundler { /* $FlowFixMe: in practice it's always here. */ this._transformer = new Transformer(opts.transformModulePath); + const getTransformCacheKey = (src, filename, options) => { + return transformCacheKey + getCacheKey(src, filename, options); + }; + this._resolver = new Resolver({ assetExts: opts.assetExts, blacklistRE: opts.blacklistRE, cache: this._cache, extraNodeModules: opts.extraNodeModules, + getTransformCacheKey, globalTransformCache: opts.globalTransformCache, minifyCode: this._transformer.minify, moduleFormat: opts.moduleFormat, @@ -160,7 +166,6 @@ class Bundler { providesModuleNodeModules: opts.providesModuleNodeModules, reporter: opts.reporter, resetCache: opts.resetCache, - transformCacheKey, transformCode: (module, code, transformCodeOptions) => this._transformer.transformFile( module.path, diff --git a/packages/metro-bundler/src/JSTransformer/index.js b/packages/metro-bundler/src/JSTransformer/index.js index cab5bf7c..77a82d89 100644 --- a/packages/metro-bundler/src/JSTransformer/index.js +++ b/packages/metro-bundler/src/JSTransformer/index.js @@ -140,8 +140,6 @@ class Transformer { static TransformError; } -module.exports = Transformer; - Transformer.TransformError = TransformError; function TransformError() { @@ -165,6 +163,8 @@ function formatGenericError(err, filename) { error.stack = stack.join('\n'); error.message = msg; error.type = 'TransformError'; + error.lineNumber = 0; + error.description = ''; return error; } @@ -180,3 +180,5 @@ function formatBabelError(err, filename) { error.description = err.message; return error; } + +module.exports = Transformer; diff --git a/packages/metro-bundler/src/Resolver/index.js b/packages/metro-bundler/src/Resolver/index.js index 2c63d473..eb8432e4 100644 --- a/packages/metro-bundler/src/Resolver/index.js +++ b/packages/metro-bundler/src/Resolver/index.js @@ -23,6 +23,7 @@ import type {Options as TransformOptions} from '../JSTransformer/worker/worker'; import type {Reporter} from '../lib/reporting'; import type {TransformCode} from '../node-haste/Module'; import type Cache from '../node-haste/Cache'; +import type {GetTransformCacheKey} from '../lib/TransformCache'; import type GlobalTransformCache from '../lib/GlobalTransformCache'; type MinifyCode = (filePath: string, code: string, map: SourceMap) => @@ -33,6 +34,7 @@ type Options = { blacklistRE?: RegExp, cache: Cache, extraNodeModules?: {}, + getTransformCacheKey: GetTransformCacheKey, globalTransformCache: ?GlobalTransformCache, minifyCode: MinifyCode, platforms: Array, @@ -41,7 +43,6 @@ type Options = { providesModuleNodeModules?: Array, reporter: Reporter, resetCache: boolean, - transformCacheKey: string, transformCode: TransformCode, watch?: boolean, }; @@ -58,6 +59,7 @@ class Resolver { assetExts: opts.assetExts, cache: opts.cache, extraNodeModules: opts.extraNodeModules, + getTransformCacheKey: opts.getTransformCacheKey, globalTransformCache: opts.globalTransformCache, ignoreFilePath: function(filepath) { return filepath.indexOf('__tests__') !== -1 || @@ -73,7 +75,6 @@ class Resolver { reporter: opts.reporter, resetCache: opts.resetCache, roots: opts.projectRoots, - transformCacheKey: opts.transformCacheKey, transformCode: opts.transformCode, watch: opts.watch || false, }); diff --git a/packages/metro-bundler/src/lib/GlobalTransformCache.js b/packages/metro-bundler/src/lib/GlobalTransformCache.js index 5775a36d..6ad265a6 100644 --- a/packages/metro-bundler/src/lib/GlobalTransformCache.js +++ b/packages/metro-bundler/src/lib/GlobalTransformCache.js @@ -20,7 +20,7 @@ const path = require('path'); const request = require('request'); import type {Options as TransformOptions} from '../JSTransformer/worker/worker'; -import type {CachedResult} from './TransformCache'; +import type {CachedResult, GetTransformCacheKey} from './TransformCache'; import type {Reporter} from './reporting'; type FetchResultURIs = ( @@ -36,7 +36,7 @@ type StoreResults = ( type FetchProps = { filePath: string, sourceCode: string, - transformCacheKey: string, + getTransformCacheKey: GetTransformCacheKey, transformOptions: TransformOptions, }; @@ -235,7 +235,7 @@ class GlobalTransformCache { const stableOptions = globalizeTransformOptions(props.transformOptions); const digest = crypto.createHash('sha1').update([ jsonStableStringify(stableOptions), - props.transformCacheKey, + props.getTransformCacheKey(props.sourceCode, props.filePath, props.transformOptions), imurmurhash(props.sourceCode).result().toString(), ].join('$')).digest('hex'); return `${digest}-${path.basename(props.filePath)}`; diff --git a/packages/metro-bundler/src/lib/TransformCache.js b/packages/metro-bundler/src/lib/TransformCache.js index 9973e71c..cdea19d9 100644 --- a/packages/metro-bundler/src/lib/TransformCache.js +++ b/packages/metro-bundler/src/lib/TransformCache.js @@ -29,11 +29,13 @@ const writeFileAtomicSync = require('write-file-atomic').sync; const CACHE_NAME = 'react-native-packager-cache'; -type CacheFilePaths = {transformedCode: string, metadata: string}; import type {Options as TransformOptions} from '../JSTransformer/worker/worker'; import type {SourceMap} from './SourceMap'; import type {Reporter} from './reporting'; +type CacheFilePaths = {transformedCode: string, metadata: string}; +export type GetTransformCacheKey = (sourceCode: string, filename: string, options: {}) => string; + /** * If packager is running for two different directories, we don't want the * caches to conflict with each other. `__dirname` carries that because packager @@ -58,10 +60,16 @@ const getCacheDirPath = (function () { })(); function hashSourceCode(props: { + filePath: string, sourceCode: string, - transformCacheKey: string, + getTransformCacheKey: GetTransformCacheKey, + transformOptions: TransformOptions, }): string { - return imurmurhash(props.transformCacheKey).hash(props.sourceCode).result(); + return imurmurhash(props.getTransformCacheKey( + props.sourceCode, + props.filePath, + props.transformOptions, + )).hash(props.sourceCode).result(); } /** @@ -125,7 +133,7 @@ function unlinkIfExistsSync(filePath: string) { function writeSync(props: { filePath: string, sourceCode: string, - transformCacheKey: string, + getTransformCacheKey: GetTransformCacheKey, transformOptions: TransformOptions, result: CachedResult, }): void { @@ -288,7 +296,7 @@ export type ReadTransformProps = { filePath: string, sourceCode: string, transformOptions: TransformOptions, - transformCacheKey: string, + getTransformCacheKey: GetTransformCacheKey, cacheOptions: CacheOptions, }; diff --git a/packages/metro-bundler/src/lib/__mocks__/TransformCache.js b/packages/metro-bundler/src/lib/__mocks__/TransformCache.js index 84e9143c..aac223ed 100644 --- a/packages/metro-bundler/src/lib/__mocks__/TransformCache.js +++ b/packages/metro-bundler/src/lib/__mocks__/TransformCache.js @@ -24,7 +24,7 @@ const mock = { const transformCacheKeyOf = (props) => props.filePath + '-' + imurmurhash(props.sourceCode) - .hash(props.transformCacheKey) + .hash(props.getTransformCacheKey(props.sourceCode, props.filePath, props.transformOptions)) .hash(jsonStableStringify(props.transformOptions || {})) .result().toString(16); diff --git a/packages/metro-bundler/src/lib/__tests__/TransformCache-test.js b/packages/metro-bundler/src/lib/__tests__/TransformCache-test.js index e2e3bece..37033fbf 100644 --- a/packages/metro-bundler/src/lib/__tests__/TransformCache-test.js +++ b/packages/metro-bundler/src/lib/__tests__/TransformCache-test.js @@ -58,12 +58,11 @@ describe('TransformCache', () => { }); it('is caching different files and options separately', () => { - const transformCacheKey = 'abcdef'; const argsFor = ([filePath, transformOptions]) => { const key = filePath + JSON.stringify(transformOptions); return { sourceCode: `/* source for ${key} */`, - transformCacheKey, + getTransformCacheKey: () => 'abcdef', filePath, transformOptions, result: { @@ -97,7 +96,7 @@ describe('TransformCache', () => { const key = sourceCode + transformCacheKey; return { sourceCode, - transformCacheKey, + getTransformCacheKey: () => transformCacheKey, filePath: 'test.js', transformOptions: {foo: 1}, result: { diff --git a/packages/metro-bundler/src/node-haste/Module.js b/packages/metro-bundler/src/node-haste/Module.js index bf75a71c..40118ec8 100644 --- a/packages/metro-bundler/src/node-haste/Module.js +++ b/packages/metro-bundler/src/node-haste/Module.js @@ -25,6 +25,7 @@ const {join: joinPath, relative: relativePath, extname} = require('path'); import type {TransformedCode, Options as TransformOptions} from '../JSTransformer/worker/worker'; import type GlobalTransformCache from '../lib/GlobalTransformCache'; import type {SourceMap} from '../lib/SourceMap'; +import type {GetTransformCacheKey} from '../lib/TransformCache'; import type {ReadTransformProps} from '../lib/TransformCache'; import type {Reporter} from '../lib/reporting'; import type Cache from './Cache'; @@ -58,7 +59,7 @@ export type ConstructorArgs = { moduleCache: ModuleCache, options: Options, reporter: Reporter, - transformCacheKey: ?string, + getTransformCacheKey: GetTransformCacheKey, transformCode: ?TransformCode, }; @@ -70,7 +71,7 @@ class Module { _moduleCache: ModuleCache; _cache: Cache; _transformCode: ?TransformCode; - _transformCacheKey: ?string; + _getTransformCacheKey: GetTransformCacheKey; _depGraphHelpers: DependencyGraphHelpers; _options: Options; _reporter: Reporter; @@ -85,11 +86,11 @@ class Module { cache, depGraphHelpers, file, + getTransformCacheKey, globalTransformCache, moduleCache, options, reporter, - transformCacheKey, transformCode, }: ConstructorArgs) { if (!isAbsolutePath(file)) { @@ -102,11 +103,7 @@ class Module { this._moduleCache = moduleCache; this._cache = cache; this._transformCode = transformCode; - this._transformCacheKey = transformCacheKey; - invariant( - transformCode == null || transformCacheKey != null, - 'missing transform cache key', - ); + this._getTransformCacheKey = getTransformCacheKey; this._depGraphHelpers = depGraphHelpers; this._options = options || {}; this._reporter = reporter; @@ -324,12 +321,11 @@ class Module { if (extern) { transformOptions = {...transformOptions, extern}; } - const transformCacheKey = this._transformCacheKey; - invariant(transformCacheKey != null, 'missing transform cache key'); + const getTransformCacheKey = this._getTransformCacheKey; const cacheProps = { filePath: this.path, sourceCode, - transformCacheKey, + getTransformCacheKey, transformOptions, cacheOptions: { resetCache: this._options.resetCache, diff --git a/packages/metro-bundler/src/node-haste/ModuleCache.js b/packages/metro-bundler/src/node-haste/ModuleCache.js index 75ad54b2..cead5fc9 100644 --- a/packages/metro-bundler/src/node-haste/ModuleCache.js +++ b/packages/metro-bundler/src/node-haste/ModuleCache.js @@ -17,6 +17,7 @@ const Package = require('./Package'); const Polyfill = require('./Polyfill'); import type GlobalTransformCache from '../lib/GlobalTransformCache'; +import type {GetTransformCacheKey} from '../lib/TransformCache'; import type {Reporter} from '../lib/reporting'; import type Cache from './Cache'; import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers'; @@ -30,13 +31,13 @@ class ModuleCache { _cache: Cache; _depGraphHelpers: DependencyGraphHelpers; _getClosestPackage: GetClosestPackageFn; + _getTransformCacheKey: GetTransformCacheKey; _globalTransformCache: ?GlobalTransformCache; _moduleCache: {[filePath: string]: Module}; _moduleOptions: ModuleOptions; _packageCache: {[filePath: string]: Package}; _packageModuleMap: WeakMap; _platforms: Set; - _transformCacheKey: string; _transformCode: TransformCode; _reporter: Reporter; @@ -46,24 +47,25 @@ class ModuleCache { depGraphHelpers, extractRequires, getClosestPackage, + getTransformCacheKey, globalTransformCache, moduleOptions, reporter, - transformCacheKey, transformCode, }: { assetDependencies: Array, cache: Cache, depGraphHelpers: DependencyGraphHelpers, getClosestPackage: GetClosestPackageFn, + getTransformCacheKey: GetTransformCacheKey, globalTransformCache: ?GlobalTransformCache, moduleOptions: ModuleOptions, reporter: Reporter, - transformCacheKey: string, transformCode: TransformCode, }, platforms: Set) { this._assetDependencies = assetDependencies; this._getClosestPackage = getClosestPackage; + this._getTransformCacheKey = getTransformCacheKey; this._globalTransformCache = globalTransformCache; this._cache = cache; this._depGraphHelpers = depGraphHelpers; @@ -72,7 +74,6 @@ class ModuleCache { this._packageCache = Object.create(null); this._packageModuleMap = new WeakMap(); this._platforms = platforms; - this._transformCacheKey = transformCacheKey; this._transformCode = transformCode; this._reporter = reporter; } @@ -83,11 +84,11 @@ class ModuleCache { cache: this._cache, depGraphHelpers: this._depGraphHelpers, file: filePath, + getTransformCacheKey: this._getTransformCacheKey, globalTransformCache: this._globalTransformCache, moduleCache: this, options: this._moduleOptions, reporter: this._reporter, - transformCacheKey: this._transformCacheKey, transformCode: this._transformCode, }); } @@ -149,9 +150,9 @@ class ModuleCache { file, cache: this._cache, depGraphHelpers: this._depGraphHelpers, + getTransformCacheKey: this._getTransformCacheKey, moduleCache: this, transformCode: this._transformCode, - transformCacheKey: this._transformCacheKey, }); } diff --git a/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js b/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js index f1983031..b87c0600 100644 --- a/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js +++ b/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js @@ -103,7 +103,6 @@ describe('DependencyGraph', function() { }); Cache.prototype.end = jest.genMockFn(); - const transformCacheKey = 'abcdef'; defaults = { assetExts: ['png', 'jpg'], cache: new Cache(), @@ -126,7 +125,7 @@ describe('DependencyGraph', function() { resolve({...deps, code: sourceCode}); }); }, - transformCacheKey, + getTransformCacheKey: () => 'abcdef', reporter: require('../../lib/reporting').nullReporter, }; }); diff --git a/packages/metro-bundler/src/node-haste/__tests__/Module-test.js b/packages/metro-bundler/src/node-haste/__tests__/Module-test.js index ad583bb7..4bcdcf70 100644 --- a/packages/metro-bundler/src/node-haste/__tests__/Module-test.js +++ b/packages/metro-bundler/src/node-haste/__tests__/Module-test.js @@ -71,7 +71,7 @@ describe('Module', () => { file: options && options.file || fileName, depGraphHelpers: new DependencyGraphHelpers(), moduleCache: new ModuleCache({cache}), - transformCacheKey, + getTransformCacheKey: () => transformCacheKey, }); const createJSONModule = @@ -188,7 +188,7 @@ describe('Module', () => { filePath: module.path, sourceCode, transformOptions: options, - transformCacheKey, + getTransformCacheKey: () => transformCacheKey, result: transformResult, }); return Promise.resolve(transformResult); diff --git a/packages/metro-bundler/src/node-haste/index.js b/packages/metro-bundler/src/node-haste/index.js index 5c64e01c..995a6498 100644 --- a/packages/metro-bundler/src/node-haste/index.js +++ b/packages/metro-bundler/src/node-haste/index.js @@ -39,6 +39,7 @@ const { import type {Options as TransformOptions} from '../JSTransformer/worker/worker'; import type GlobalTransformCache from '../lib/GlobalTransformCache'; +import type {GetTransformCacheKey} from '../lib/TransformCache'; import type {Reporter} from '../lib/reporting'; import type { Options as ModuleOptions, @@ -65,7 +66,7 @@ class DependencyGraph { resetCache: boolean, roots: Array, shouldThrowOnUnresolvedErrors: () => boolean, - transformCacheKey: string, + getTransformCacheKey: GetTransformCacheKey, transformCode: TransformCode, useWatchman: boolean, watch: boolean, @@ -89,6 +90,7 @@ class DependencyGraph { extensions, extraNodeModules, forceNodeFilesystemAPI, + getTransformCacheKey, globalTransformCache, ignoreFilePath, maxWorkers, @@ -100,7 +102,6 @@ class DependencyGraph { resetCache, roots, shouldThrowOnUnresolvedErrors = () => true, - transformCacheKey, transformCode, useWatchman, watch, @@ -112,6 +113,7 @@ class DependencyGraph { extensions?: ?Array, extraNodeModules: ?Object, forceNodeFilesystemAPI?: boolean, + getTransformCacheKey: GetTransformCacheKey, globalTransformCache: ?GlobalTransformCache, ignoreFilePath: (filePath: string) => boolean, maxWorkers?: ?number, @@ -123,7 +125,6 @@ class DependencyGraph { resetCache: boolean, roots: Array, shouldThrowOnUnresolvedErrors?: () => boolean, - transformCacheKey: string, transformCode: TransformCode, useWatchman?: ?boolean, watch: boolean, @@ -134,6 +135,7 @@ class DependencyGraph { extensions: extensions || ['js', 'json'], extraNodeModules, forceNodeFilesystemAPI: !!forceNodeFilesystemAPI, + getTransformCacheKey, globalTransformCache, ignoreFilePath: ignoreFilePath || (() => {}), maxWorkers, @@ -147,7 +149,6 @@ class DependencyGraph { resetCache, roots, shouldThrowOnUnresolvedErrors, - transformCacheKey, transformCode, useWatchman: useWatchman !== false, watch: !!watch, @@ -191,9 +192,9 @@ class DependencyGraph { this._moduleCache = new ModuleCache({ cache: this._cache, + getTransformCacheKey: this._opts.getTransformCacheKey, globalTransformCache: this._opts.globalTransformCache, transformCode: this._opts.transformCode, - transformCacheKey: this._opts.transformCacheKey, depGraphHelpers: this._helpers, assetDependencies: this._assetDependencies, moduleOptions: this._opts.moduleOptions,