mirror of https://github.com/status-im/metro.git
Clean-up Module methods/properties
Reviewed By: jeanlauliac Differential Revision: D7894084 fbshipit-source-id: 1a4826d272da51f8beea44ba9b82fa685d254fbe
This commit is contained in:
parent
9a1bfe6388
commit
e47fdf6f59
|
@ -137,22 +137,17 @@ class Bundler {
|
||||||
|
|
||||||
this._depGraphPromise = DependencyGraph.load({
|
this._depGraphPromise = DependencyGraph.load({
|
||||||
assetExts: opts.assetExts,
|
assetExts: opts.assetExts,
|
||||||
assetRegistryPath: opts.assetRegistryPath,
|
|
||||||
blacklistRE: opts.blacklistRE,
|
blacklistRE: opts.blacklistRE,
|
||||||
experimentalCaches: true,
|
|
||||||
extraNodeModules: opts.extraNodeModules,
|
extraNodeModules: opts.extraNodeModules,
|
||||||
getPolyfills: opts.getPolyfills,
|
|
||||||
hasteImplModulePath: opts.hasteImplModulePath,
|
hasteImplModulePath: opts.hasteImplModulePath,
|
||||||
maxWorkers: opts.maxWorkers,
|
maxWorkers: opts.maxWorkers,
|
||||||
platforms: new Set(opts.platforms),
|
platforms: new Set(opts.platforms),
|
||||||
polyfillModuleNames: opts.polyfillModuleNames,
|
|
||||||
projectRoots: opts.projectRoots,
|
projectRoots: opts.projectRoots,
|
||||||
providesModuleNodeModules:
|
providesModuleNodeModules:
|
||||||
opts.providesModuleNodeModules || defaults.providesModuleNodeModules,
|
opts.providesModuleNodeModules || defaults.providesModuleNodeModules,
|
||||||
reporter: opts.reporter,
|
reporter: opts.reporter,
|
||||||
resolveRequest: opts.resolveRequest,
|
resolveRequest: opts.resolveRequest,
|
||||||
sourceExts: opts.sourceExts,
|
sourceExts: opts.sourceExts,
|
||||||
transformCode: this.transformFile.bind(this),
|
|
||||||
watch: opts.watch,
|
watch: opts.watch,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,8 @@ beforeEach(() => {
|
||||||
|
|
||||||
describe('traverseDependencies', function() {
|
describe('traverseDependencies', function() {
|
||||||
let fs;
|
let fs;
|
||||||
let Module;
|
|
||||||
let traverseDependencies;
|
let traverseDependencies;
|
||||||
|
let transformFile;
|
||||||
let transformHelpers;
|
let transformHelpers;
|
||||||
let defaults;
|
let defaults;
|
||||||
let UnableToResolveError;
|
let UnableToResolveError;
|
||||||
|
@ -97,7 +97,7 @@ describe('traverseDependencies', function() {
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
[...dependencies].map(async path => {
|
[...dependencies].map(async path => {
|
||||||
const dep = dgraph.getModuleForPath(path);
|
const dep = dgraph.getModuleForPath(path);
|
||||||
const moduleDependencies = (await dep.read()).dependencies;
|
const moduleDependencies = (await transformFile(path)).dependencies;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path: dep.path,
|
path: dep.path,
|
||||||
|
@ -115,7 +115,6 @@ describe('traverseDependencies', function() {
|
||||||
jest.mock('fs', () => new (require('metro-memory-fs'))());
|
jest.mock('fs', () => new (require('metro-memory-fs'))());
|
||||||
|
|
||||||
fs = require('fs');
|
fs = require('fs');
|
||||||
Module = require('../../node-haste/Module');
|
|
||||||
traverseDependencies = require('../traverseDependencies');
|
traverseDependencies = require('../traverseDependencies');
|
||||||
transformHelpers = require('../../lib/transformHelpers');
|
transformHelpers = require('../../lib/transformHelpers');
|
||||||
({
|
({
|
||||||
|
@ -131,24 +130,23 @@ describe('traverseDependencies', function() {
|
||||||
platforms: new Set(['ios', 'android']),
|
platforms: new Set(['ios', 'android']),
|
||||||
maxWorkers: 1,
|
maxWorkers: 1,
|
||||||
resetCache: true,
|
resetCache: true,
|
||||||
transformCode: (module, sourceCode, transformOptions) => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
// require call must stay inline, so the latest defined mock is used!
|
|
||||||
const code = require('fs').readFileSync(module.path, 'utf8');
|
|
||||||
const deps = {dependencies: []};
|
|
||||||
|
|
||||||
if (!module.path.endsWith('.json')) {
|
|
||||||
deps.dependencies = extractDependencies(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve({...deps, code});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getTransformCacheKey: () => 'abcdef',
|
getTransformCacheKey: () => 'abcdef',
|
||||||
reporter: require('../../lib/reporting').nullReporter,
|
reporter: require('../../lib/reporting').nullReporter,
|
||||||
sourceExts: ['js', 'json'],
|
sourceExts: ['js', 'json'],
|
||||||
watch: true,
|
watch: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
transformFile = async filePath => {
|
||||||
|
// require call must stay inline, so the latest defined mock is used!
|
||||||
|
const code = require('fs').readFileSync(filePath, 'utf8');
|
||||||
|
const deps = {dependencies: []};
|
||||||
|
|
||||||
|
if (!filePath.endsWith('.json')) {
|
||||||
|
deps.dependencies = extractDependencies(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {...deps, code};
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('get sync dependencies (posix)', () => {
|
describe('get sync dependencies (posix)', () => {
|
||||||
|
@ -3462,46 +3460,13 @@ describe('traverseDependencies', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Asset module dependencies', () => {
|
|
||||||
let DependencyGraph;
|
|
||||||
let processDgraph;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
DependencyGraph = require('../../node-haste/DependencyGraph');
|
|
||||||
processDgraph = processDgraphFor.bind(null, DependencyGraph);
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('allows setting dependencies for asset modules (broken)', async () => {
|
|
||||||
const assetDependencies = ['/root/apple.png', '/root/banana.png'];
|
|
||||||
|
|
||||||
setMockFileSystem({
|
|
||||||
root: {
|
|
||||||
'index.js': 'require("./a.png")',
|
|
||||||
'a.png': '',
|
|
||||||
'apple.png': '',
|
|
||||||
'banana.png': '',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const opts = {...defaults, assetDependencies, projectRoots: ['/root']};
|
|
||||||
await processDgraph(opts, async dgraph => {
|
|
||||||
const {dependencies} = await dgraph.getDependencies({
|
|
||||||
entryPath: '/root/index.js',
|
|
||||||
});
|
|
||||||
const [, assetModule] = dependencies;
|
|
||||||
const deps = await assetModule.getDependencies();
|
|
||||||
expect(deps).toBe(assetDependencies);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Deterministic order of dependencies', () => {
|
describe('Deterministic order of dependencies', () => {
|
||||||
let callDeferreds, dependencyGraph, moduleReadDeferreds;
|
let callDeferreds, dependencyGraph, moduleReadDeferreds;
|
||||||
let moduleRead;
|
let originalTransformFile;
|
||||||
let DependencyGraph;
|
let DependencyGraph;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
moduleRead = Module.prototype.read;
|
originalTransformFile = transformFile;
|
||||||
DependencyGraph = require('../../node-haste/DependencyGraph');
|
DependencyGraph = require('../../node-haste/DependencyGraph');
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
root: {
|
root: {
|
||||||
|
@ -3533,13 +3498,13 @@ describe('traverseDependencies', function() {
|
||||||
moduleReadDeferreds = {};
|
moduleReadDeferreds = {};
|
||||||
callDeferreds = [defer(), defer()]; // [a.js, b.js]
|
callDeferreds = [defer(), defer()]; // [a.js, b.js]
|
||||||
|
|
||||||
Module.prototype.read = jest.genMockFn().mockImplementation(function() {
|
transformFile = jest.genMockFn().mockImplementation((path, ...args) => {
|
||||||
const returnValue = moduleRead.apply(this, arguments);
|
const returnValue = originalTransformFile(path, ...args);
|
||||||
if (/\/[ab]\.js$/.test(this.path)) {
|
if (/\/[ab]\.js$/.test(path)) {
|
||||||
let deferred = moduleReadDeferreds[this.path];
|
let deferred = moduleReadDeferreds[path];
|
||||||
if (!deferred) {
|
if (!deferred) {
|
||||||
deferred = moduleReadDeferreds[this.path] = defer(returnValue);
|
deferred = moduleReadDeferreds[path] = defer(returnValue);
|
||||||
const index = Number(this.path.endsWith('b.js')); // 0 or 1
|
const index = Number(path.endsWith('b.js')); // 0 or 1
|
||||||
callDeferreds[index].resolve();
|
callDeferreds[index].resolve();
|
||||||
}
|
}
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
|
@ -3551,7 +3516,7 @@ describe('traverseDependencies', function() {
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
dependencyGraph.then(dgraph => dgraph.end());
|
dependencyGraph.then(dgraph => dgraph.end());
|
||||||
Module.prototype.read = moduleRead;
|
transformFile = originalTransformFile;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('produces a deterministic tree if the "a" module resolves first', () => {
|
it('produces a deterministic tree if the "a" module resolves first', () => {
|
||||||
|
|
|
@ -115,7 +115,7 @@ async function getResolveDependencyFn(
|
||||||
|
|
||||||
return (from: string, to: string) => {
|
return (from: string, to: string) => {
|
||||||
return dependencyGraph.resolveDependency(
|
return dependencyGraph.resolveDependency(
|
||||||
dependencyGraph.getModuleForPath(from, false),
|
dependencyGraph.getModuleForPath(from),
|
||||||
to,
|
to,
|
||||||
platform,
|
platform,
|
||||||
).path;
|
).path;
|
||||||
|
|
|
@ -19,7 +19,6 @@ const ModuleCache = require('./ModuleCache');
|
||||||
const ResolutionRequest = require('./DependencyGraph/ResolutionRequest');
|
const ResolutionRequest = require('./DependencyGraph/ResolutionRequest');
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const parsePlatformFilePath = require('./lib/parsePlatformFilePath');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const toLocalPath = require('../node-haste/lib/toLocalPath');
|
const toLocalPath = require('../node-haste/lib/toLocalPath');
|
||||||
|
|
||||||
|
@ -29,32 +28,24 @@ const {
|
||||||
Logger: {createActionStartEntry, createActionEndEntry, log},
|
Logger: {createActionStartEntry, createActionEndEntry, log},
|
||||||
} = require('metro-core');
|
} = require('metro-core');
|
||||||
|
|
||||||
import type {WorkerOptions} from '../JSTransformer/worker';
|
|
||||||
import type {TransformResultDependency} from '../ModuleGraph/types.flow';
|
|
||||||
import type {Reporter} from '../lib/reporting';
|
import type {Reporter} from '../lib/reporting';
|
||||||
import type {ModuleMap} from './DependencyGraph/ModuleResolution';
|
import type {ModuleMap} from './DependencyGraph/ModuleResolution';
|
||||||
import type {TransformCode} from './Module';
|
|
||||||
import type Package from './Package';
|
import type Package from './Package';
|
||||||
import type {HasteFS} from './types';
|
import type {HasteFS} from './types';
|
||||||
import type {CustomResolver} from 'metro-resolver';
|
import type {CustomResolver} from 'metro-resolver';
|
||||||
|
|
||||||
type Options = {|
|
type Options = {|
|
||||||
+assetExts: Array<string>,
|
+assetExts: Array<string>,
|
||||||
+assetRegistryPath: string,
|
|
||||||
+blacklistRE?: RegExp,
|
+blacklistRE?: RegExp,
|
||||||
+experimentalCaches: boolean,
|
|
||||||
+extraNodeModules: ?{},
|
+extraNodeModules: ?{},
|
||||||
+getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>,
|
|
||||||
+hasteImplModulePath?: string,
|
+hasteImplModulePath?: string,
|
||||||
+maxWorkers: number,
|
+maxWorkers: number,
|
||||||
+platforms: Set<string>,
|
+platforms: Set<string>,
|
||||||
+polyfillModuleNames?: Array<string>,
|
|
||||||
+projectRoots: $ReadOnlyArray<string>,
|
+projectRoots: $ReadOnlyArray<string>,
|
||||||
+providesModuleNodeModules: Array<string>,
|
+providesModuleNodeModules: Array<string>,
|
||||||
+reporter: Reporter,
|
+reporter: Reporter,
|
||||||
+resolveRequest: ?CustomResolver,
|
+resolveRequest: ?CustomResolver,
|
||||||
+sourceExts: Array<string>,
|
+sourceExts: Array<string>,
|
||||||
+transformCode: TransformCode,
|
|
||||||
+watch: boolean,
|
+watch: boolean,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
|
@ -195,30 +186,14 @@ class DependencyGraph extends EventEmitter {
|
||||||
const {_opts} = this;
|
const {_opts} = this;
|
||||||
return new ModuleCache(
|
return new ModuleCache(
|
||||||
{
|
{
|
||||||
assetDependencies: [_opts.assetRegistryPath],
|
|
||||||
getClosestPackage: this._getClosestPackage.bind(this),
|
getClosestPackage: this._getClosestPackage.bind(this),
|
||||||
hasteImplModulePath: _opts.hasteImplModulePath,
|
hasteImplModulePath: _opts.hasteImplModulePath,
|
||||||
roots: _opts.projectRoots,
|
roots: _opts.projectRoots,
|
||||||
transformCode: _opts.transformCode,
|
|
||||||
},
|
},
|
||||||
_opts.platforms,
|
_opts.platforms,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a promise with the direct dependencies the module associated to
|
|
||||||
* the given entryPath has.
|
|
||||||
*/
|
|
||||||
async getShallowDependencies(
|
|
||||||
entryPath: string,
|
|
||||||
transformOptions: WorkerOptions,
|
|
||||||
): Promise<$ReadOnlyArray<TransformResultDependency>> {
|
|
||||||
const module = this._moduleCache.getModule(entryPath);
|
|
||||||
const result = await module.read(transformOptions);
|
|
||||||
|
|
||||||
return result.dependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSha1(filename: string): string {
|
getSha1(filename: string): string {
|
||||||
const sha1 = this._hasteFS.getSha1(filename);
|
const sha1 = this._hasteFS.getSha1(filename);
|
||||||
|
|
||||||
|
@ -237,11 +212,7 @@ class DependencyGraph extends EventEmitter {
|
||||||
this._haste.end();
|
this._haste.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
getModuleForPath(entryFile: string, isPolyfill: boolean): Module {
|
getModuleForPath(entryFile: string): Module {
|
||||||
if (isPolyfill) {
|
|
||||||
return this._moduleCache.getPolyfillModule(entryFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._helpers.isAssetFile(entryFile)) {
|
if (this._helpers.isAssetFile(entryFile)) {
|
||||||
return this._moduleCache.getAssetModule(entryFile);
|
return this._moduleCache.getAssetModule(entryFile);
|
||||||
}
|
}
|
||||||
|
@ -269,16 +240,6 @@ class DependencyGraph extends EventEmitter {
|
||||||
return this._hasteFS.exists(filePath);
|
return this._hasteFS.exists(filePath);
|
||||||
};
|
};
|
||||||
|
|
||||||
_getRequestPlatform(entryPath: string, platform: ?string): ?string {
|
|
||||||
if (platform == null) {
|
|
||||||
platform = parsePlatformFilePath(entryPath, this._opts.platforms)
|
|
||||||
.platform;
|
|
||||||
} else if (!this._opts.platforms.has(platform)) {
|
|
||||||
throw new Error('Unrecognized platform: ' + platform);
|
|
||||||
}
|
|
||||||
return platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
getHasteName(filePath: string): string {
|
getHasteName(filePath: string): string {
|
||||||
const hasteName = this._hasteFS.getModuleName(filePath);
|
const hasteName = this._hasteFS.getModuleName(filePath);
|
||||||
|
|
||||||
|
@ -288,10 +249,6 @@ class DependencyGraph extends EventEmitter {
|
||||||
|
|
||||||
return toLocalPath(this._opts.projectRoots, filePath);
|
return toLocalPath(this._opts.projectRoots, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
createPolyfill(options: {file: string}) {
|
|
||||||
return this._moduleCache.createPolyfill(options);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DependencyGraph;
|
module.exports = DependencyGraph;
|
||||||
|
|
|
@ -10,25 +10,15 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const isAbsolutePath = require('absolute-path');
|
const isAbsolutePath = require('absolute-path');
|
||||||
|
|
||||||
import type {TransformedCode, WorkerOptions} from '../JSTransformer/worker';
|
|
||||||
import type ModuleCache from './ModuleCache';
|
import type ModuleCache from './ModuleCache';
|
||||||
import type {LocalPath} from './lib/toLocalPath';
|
import type {LocalPath} from './lib/toLocalPath';
|
||||||
|
|
||||||
type ReadResult = {
|
|
||||||
...TransformedCode,
|
|
||||||
+source: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TransformCode = Function;
|
|
||||||
|
|
||||||
export type ConstructorArgs = {
|
export type ConstructorArgs = {
|
||||||
file: string,
|
file: string,
|
||||||
localPath: LocalPath,
|
localPath: LocalPath,
|
||||||
moduleCache: ModuleCache,
|
moduleCache: ModuleCache,
|
||||||
transformCode: TransformCode,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Module {
|
class Module {
|
||||||
|
@ -36,10 +26,9 @@ class Module {
|
||||||
path: string;
|
path: string;
|
||||||
|
|
||||||
_moduleCache: ModuleCache;
|
_moduleCache: ModuleCache;
|
||||||
_transformCode: TransformCode;
|
|
||||||
_sourceCode: ?string;
|
_sourceCode: ?string;
|
||||||
|
|
||||||
constructor({file, localPath, moduleCache, transformCode}: ConstructorArgs) {
|
constructor({file, localPath, moduleCache}: ConstructorArgs) {
|
||||||
if (!isAbsolutePath(file)) {
|
if (!isAbsolutePath(file)) {
|
||||||
throw new Error('Expected file to be absolute path but got ' + file);
|
throw new Error('Expected file to be absolute path but got ' + file);
|
||||||
}
|
}
|
||||||
|
@ -48,41 +37,13 @@ class Module {
|
||||||
this.path = file;
|
this.path = file;
|
||||||
|
|
||||||
this._moduleCache = moduleCache;
|
this._moduleCache = moduleCache;
|
||||||
this._transformCode = transformCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPackage() {
|
getPackage() {
|
||||||
return this._moduleCache.getPackageForModule(this);
|
return this._moduleCache.getPackageForModule(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate() {
|
invalidate() {}
|
||||||
this._sourceCode = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_readSourceCode(): string {
|
|
||||||
if (this._sourceCode == null) {
|
|
||||||
this._sourceCode = fs.readFileSync(this.path, 'utf8');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._sourceCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
async read(transformOptions: WorkerOptions): Promise<ReadResult> {
|
|
||||||
const result: TransformedCode = await this._transformCode(
|
|
||||||
this,
|
|
||||||
transformOptions,
|
|
||||||
);
|
|
||||||
|
|
||||||
const module = this;
|
|
||||||
|
|
||||||
return {
|
|
||||||
dependencies: result.dependencies,
|
|
||||||
output: result.output,
|
|
||||||
get source() {
|
|
||||||
return module._readSourceCode();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
isAsset() {
|
isAsset() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -13,48 +13,34 @@
|
||||||
const AssetModule = require('./AssetModule');
|
const AssetModule = require('./AssetModule');
|
||||||
const Module = require('./Module');
|
const Module = require('./Module');
|
||||||
const Package = require('./Package');
|
const Package = require('./Package');
|
||||||
const Polyfill = require('./Polyfill');
|
|
||||||
|
|
||||||
const toLocalPath = require('./lib/toLocalPath');
|
const toLocalPath = require('./lib/toLocalPath');
|
||||||
|
|
||||||
import type {TransformCode} from './Module';
|
|
||||||
|
|
||||||
type GetClosestPackageFn = (filePath: string) => ?string;
|
type GetClosestPackageFn = (filePath: string) => ?string;
|
||||||
|
|
||||||
type Options = {|
|
type Options = {|
|
||||||
assetDependencies: Array<string>,
|
|
||||||
hasteImplModulePath?: string,
|
hasteImplModulePath?: string,
|
||||||
getClosestPackage: GetClosestPackageFn,
|
getClosestPackage: GetClosestPackageFn,
|
||||||
roots: $ReadOnlyArray<string>,
|
roots: $ReadOnlyArray<string>,
|
||||||
transformCode: TransformCode,
|
|
||||||
|};
|
|};
|
||||||
|
|
||||||
class ModuleCache {
|
class ModuleCache {
|
||||||
_assetDependencies: Array<string>;
|
|
||||||
_getClosestPackage: GetClosestPackageFn;
|
_getClosestPackage: GetClosestPackageFn;
|
||||||
_moduleCache: {[filePath: string]: Module, __proto__: null};
|
_moduleCache: {[filePath: string]: Module, __proto__: null};
|
||||||
_packageCache: {[filePath: string]: Package, __proto__: null};
|
_packageCache: {[filePath: string]: Package, __proto__: null};
|
||||||
_packageModuleMap: WeakMap<Module, string>;
|
_packageModuleMap: WeakMap<Module, string>;
|
||||||
_platforms: Set<string>;
|
_platforms: Set<string>;
|
||||||
_transformCode: TransformCode;
|
|
||||||
_roots: $ReadOnlyArray<string>;
|
_roots: $ReadOnlyArray<string>;
|
||||||
_opts: Options;
|
_opts: Options;
|
||||||
|
|
||||||
constructor(options: Options, platforms: Set<string>) {
|
constructor(options: Options, platforms: Set<string>) {
|
||||||
const {
|
const {getClosestPackage, roots} = options;
|
||||||
assetDependencies,
|
|
||||||
getClosestPackage,
|
|
||||||
roots,
|
|
||||||
transformCode,
|
|
||||||
} = options;
|
|
||||||
this._opts = options;
|
this._opts = options;
|
||||||
this._assetDependencies = assetDependencies;
|
|
||||||
this._getClosestPackage = getClosestPackage;
|
this._getClosestPackage = getClosestPackage;
|
||||||
this._moduleCache = Object.create(null);
|
this._moduleCache = Object.create(null);
|
||||||
this._packageCache = Object.create(null);
|
this._packageCache = Object.create(null);
|
||||||
this._packageModuleMap = new WeakMap();
|
this._packageModuleMap = new WeakMap();
|
||||||
this._platforms = platforms;
|
this._platforms = platforms;
|
||||||
this._transformCode = transformCode;
|
|
||||||
this._roots = roots;
|
this._roots = roots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +51,6 @@ class ModuleCache {
|
||||||
localPath: toLocalPath(this._roots, filePath),
|
localPath: toLocalPath(this._roots, filePath),
|
||||||
moduleCache: this,
|
moduleCache: this,
|
||||||
options: this._getModuleOptions(),
|
options: this._getModuleOptions(),
|
||||||
transformCode: this._transformCode,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this._moduleCache[filePath];
|
return this._moduleCache[filePath];
|
||||||
|
@ -86,20 +71,11 @@ class ModuleCache {
|
||||||
localPath: toLocalPath(this._roots, filePath),
|
localPath: toLocalPath(this._roots, filePath),
|
||||||
moduleCache: this,
|
moduleCache: this,
|
||||||
options: this._getModuleOptions(),
|
options: this._getModuleOptions(),
|
||||||
transformCode: this._transformCode,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this._moduleCache[filePath];
|
return this._moduleCache[filePath];
|
||||||
}
|
}
|
||||||
|
|
||||||
getPolyfillModule(filePath: string) {
|
|
||||||
if (!this._moduleCache[filePath]) {
|
|
||||||
this._moduleCache[filePath] = this.createPolyfill({file: filePath});
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._moduleCache[filePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
getPackage(filePath: string): Package {
|
getPackage(filePath: string): Package {
|
||||||
if (!this._packageCache[filePath]) {
|
if (!this._packageCache[filePath]) {
|
||||||
this._packageCache[filePath] = new Package({
|
this._packageCache[filePath] = new Package({
|
||||||
|
@ -128,17 +104,6 @@ class ModuleCache {
|
||||||
return this.getPackage(packagePath);
|
return this.getPackage(packagePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
createPolyfill({file}: {file: string}) {
|
|
||||||
/* $FlowFixMe: there are missing arguments. */
|
|
||||||
return new Polyfill({
|
|
||||||
file,
|
|
||||||
localPath: toLocalPath(this._roots, file),
|
|
||||||
moduleCache: this,
|
|
||||||
options: this._getModuleOptions(),
|
|
||||||
transformCode: this._transformCode,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
processFileChange(type: string, filePath: string) {
|
processFileChange(type: string, filePath: string) {
|
||||||
if (this._moduleCache[filePath]) {
|
if (this._moduleCache[filePath]) {
|
||||||
this._moduleCache[filePath].invalidate();
|
this._moduleCache[filePath].invalidate();
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2013-present, Facebook, Inc.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
* @format
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const Module = require('./Module');
|
|
||||||
|
|
||||||
import type {ConstructorArgs} from './Module';
|
|
||||||
|
|
||||||
class Polyfill extends Module {
|
|
||||||
_id: string;
|
|
||||||
_dependencies: Array<string>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
options: ConstructorArgs & {
|
|
||||||
id: string,
|
|
||||||
dependencies: Array<string>,
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
super(options);
|
|
||||||
this._id = options.id;
|
|
||||||
this._dependencies = options.dependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
isHaste() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getName() {
|
|
||||||
return this._id;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPackage() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDependencies() {
|
|
||||||
return this._dependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
isPolyfill() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Polyfill;
|
|
|
@ -10,43 +10,10 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
jest.mock('fs', () => new (require('metro-memory-fs'))());
|
|
||||||
|
|
||||||
const AssetModule = require('../AssetModule');
|
const AssetModule = require('../AssetModule');
|
||||||
const DependencyGraphHelpers = require('../DependencyGraph/DependencyGraphHelpers');
|
|
||||||
const ModuleCache = require('../ModuleCache');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
describe('AssetModule:', () => {
|
describe('AssetModule:', () => {
|
||||||
const defaults = {file: '/arbitrary.png'};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fs.reset();
|
|
||||||
fs.mkdirSync('/root');
|
|
||||||
fs.writeFileSync('/root/image.png', 'png data');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('is an asset', () => {
|
it('is an asset', () => {
|
||||||
expect(new AssetModule(defaults).isAsset()).toBe(true);
|
expect(new AssetModule({file: '/arbitrary.png'}).isAsset()).toBe(true);
|
||||||
});
|
|
||||||
|
|
||||||
it('returns an empty source code for an asset', async () => {
|
|
||||||
const module = new AssetModule({
|
|
||||||
depGraphHelpers: new DependencyGraphHelpers({
|
|
||||||
providesModuleNodeModules: [],
|
|
||||||
assetExts: ['png'],
|
|
||||||
}),
|
|
||||||
file: '/root/image.png',
|
|
||||||
getTransformCacheKey: () => 'foo',
|
|
||||||
localPath: 'image.png',
|
|
||||||
moduleCache: new ModuleCache({}),
|
|
||||||
transformCode: () => {
|
|
||||||
return Promise.resolve({output: [{code: 'module.exports = "asset";'}]});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await module.read();
|
|
||||||
|
|
||||||
expect(data.output[0].code).toBe('module.exports = "asset";');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,37 +10,23 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
jest.mock('fs').mock('../ModuleCache');
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const ModuleCache = require('../ModuleCache');
|
|
||||||
const Module = require('../Module');
|
const Module = require('../Module');
|
||||||
|
const ModuleCache = require('../ModuleCache');
|
||||||
|
|
||||||
describe('Module', () => {
|
describe('Module', () => {
|
||||||
let transformCode;
|
|
||||||
let moduleCache;
|
let moduleCache;
|
||||||
let module;
|
let module;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
transformCode = jest.fn().mockReturnValue({
|
moduleCache = new ModuleCache({});
|
||||||
dependencies: ['stdlib.h', 'conio.h'],
|
|
||||||
output: [{code: 'int main(void) { return -1; }', map: []}],
|
|
||||||
});
|
|
||||||
|
|
||||||
moduleCache = new ModuleCache();
|
|
||||||
|
|
||||||
module = new Module({
|
module = new Module({
|
||||||
file: '/root/to/file.js',
|
file: '/root/to/file.js',
|
||||||
localPath: 'file.js',
|
localPath: 'file.js',
|
||||||
moduleCache,
|
moduleCache,
|
||||||
transformCode,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
fs.readFileSync.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Returns the correct values for many properties and methods', () => {
|
it('Returns the correct values for many properties and methods', () => {
|
||||||
expect(module.localPath).toBe('file.js');
|
expect(module.localPath).toBe('file.js');
|
||||||
expect(module.path).toBe('/root/to/file.js');
|
expect(module.path).toBe('/root/to/file.js');
|
||||||
|
@ -48,43 +34,4 @@ describe('Module', () => {
|
||||||
expect(module.isAsset()).toBe(false);
|
expect(module.isAsset()).toBe(false);
|
||||||
expect(module.isPolyfill()).toBe(false);
|
expect(module.isPolyfill()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the result from the transform code straight away', async () => {
|
|
||||||
fs.readFileSync.mockReturnValue('original code');
|
|
||||||
|
|
||||||
expect(await module.read({})).toEqual({
|
|
||||||
dependencies: ['stdlib.h', 'conio.h'],
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
code: 'int main(void) { return -1; }',
|
|
||||||
|
|
||||||
map: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
source: 'original code',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('checks that code is only read once until invalidated', async () => {
|
|
||||||
fs.readFileSync.mockReturnValue('original code');
|
|
||||||
|
|
||||||
// Read once. No access to "source", so no reads.
|
|
||||||
await module.read({});
|
|
||||||
expect(fs.readFileSync).toHaveBeenCalledTimes(0);
|
|
||||||
|
|
||||||
// Read again, accessing "source".
|
|
||||||
expect((await module.read({})).source).toEqual('original code');
|
|
||||||
expect(fs.readFileSync).toHaveBeenCalledTimes(1);
|
|
||||||
|
|
||||||
// Read again, accessing "source" again. Still 1 because code was cached.
|
|
||||||
expect((await module.read({})).source).toEqual('original code');
|
|
||||||
expect(fs.readFileSync).toHaveBeenCalledTimes(1);
|
|
||||||
|
|
||||||
// Invalidate.
|
|
||||||
module.invalidate();
|
|
||||||
|
|
||||||
// Read again, this time it will read it.
|
|
||||||
expect((await module.read({})).source).toEqual('original code');
|
|
||||||
expect(fs.readFileSync).toHaveBeenCalledTimes(2);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue