packager: MapWithDefaults: @flow
Summary: It was hard to type the resolution main algo, I had to put type annotations explicitely everywhere, otherwise Flow would get in some kind of loop and do weird errors. I think it's because the algo is recursive and Flow tries to infer types too deeply because of the generics. Anyway, apart from that it's good to get this extra type security in the few other places. We require Node v4 minimum, that according to the internets supports the `class` syntax without transform, and I verified that inheriting from `Map` actually works as expected. Reviewed By: davidaurelio Differential Revision: D5078023 fbshipit-source-id: 05dfc4acf5b07cdda8a7b36ec9cba216d1810643
This commit is contained in:
parent
0357303f5b
commit
e6bc8ea10a
|
@ -642,7 +642,7 @@ class Bundler {
|
||||||
entryFilePath: string,
|
entryFilePath: string,
|
||||||
options: BundlingOptions,
|
options: BundlingOptions,
|
||||||
getModuleId: () => number,
|
getModuleId: () => number,
|
||||||
dependencyPairs: Array<[mixed, {path: string}]>,
|
dependencyPairs: Array<[string, Module]>,
|
||||||
assetPlugins: Array<string>,
|
assetPlugins: Array<string>,
|
||||||
}): Promise<ModuleTransport> {
|
}): Promise<ModuleTransport> {
|
||||||
let moduleTransport;
|
let moduleTransport;
|
||||||
|
|
|
@ -552,6 +552,7 @@ class Server {
|
||||||
changedModules.forEach(m => {
|
changedModules.forEach(m => {
|
||||||
response.setResolvedDependencyPairs(
|
response.setResolvedDependencyPairs(
|
||||||
m,
|
m,
|
||||||
|
/* $FlowFixMe: should be enforced not to be null. */
|
||||||
dependencyPairs.get(m.path),
|
dependencyPairs.get(m.path),
|
||||||
{ignoreFinalized: true},
|
{ignoreFinalized: true},
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,13 +12,14 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import type {RawMapping} from '../Bundler/source-map';
|
import type {RawMapping} from '../Bundler/source-map';
|
||||||
|
import type Module from '../node-haste/Module';
|
||||||
import type {SourceMap} from './SourceMap';
|
import type {SourceMap} from './SourceMap';
|
||||||
|
|
||||||
type SourceMapOrMappings = SourceMap | Array<RawMapping>;
|
type SourceMapOrMappings = SourceMap | Array<RawMapping>;
|
||||||
|
|
||||||
type Metadata = {
|
type Metadata = {
|
||||||
dependencies?: ?Array<string>,
|
dependencies?: ?Array<string>,
|
||||||
dependencyPairs?: Array<[mixed, {path: string}]>,
|
dependencyPairs?: Array<[string, Module]>,
|
||||||
preloaded: ?boolean,
|
preloaded: ?boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -214,9 +214,10 @@ class ResolutionRequest<TModule: Moduleish, TPackage: Packageish> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const collectedDependencies = new MapWithDefaults(module =>
|
const collectedDependencies: MapWithDefaults<
|
||||||
collect(module),
|
TModule,
|
||||||
);
|
Promise<Array<TModule>>,
|
||||||
|
> = new MapWithDefaults(module => collect(module));
|
||||||
const crawlDependencies = (mod, [depNames, dependencies]) => {
|
const crawlDependencies = (mod, [depNames, dependencies]) => {
|
||||||
const filteredPairs = [];
|
const filteredPairs = [];
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import type Module from '../Module';
|
|
||||||
|
|
||||||
const NO_OPTIONS = {};
|
const NO_OPTIONS = {};
|
||||||
|
|
||||||
class ResolutionResponse<TModule: {hash(): string}, TOptions> {
|
class ResolutionResponse<TModule: {hash(): string}, TOptions> {
|
||||||
|
@ -26,7 +24,7 @@ class ResolutionResponse<TModule: {hash(): string}, TOptions> {
|
||||||
// This is monkey-patched from Resolver.
|
// This is monkey-patched from Resolver.
|
||||||
getModuleId: ?() => number;
|
getModuleId: ?() => number;
|
||||||
|
|
||||||
_mappings: {};
|
_mappings: {[hash: string]: Array<[string, TModule]>};
|
||||||
_finalized: boolean;
|
_finalized: boolean;
|
||||||
_mainModule: ?TModule;
|
_mainModule: ?TModule;
|
||||||
|
|
||||||
|
@ -104,8 +102,8 @@ class ResolutionResponse<TModule: {hash(): string}, TOptions> {
|
||||||
}
|
}
|
||||||
|
|
||||||
setResolvedDependencyPairs(
|
setResolvedDependencyPairs(
|
||||||
module: Module,
|
module: TModule,
|
||||||
pairs: mixed,
|
pairs: Array<[string, TModule]>,
|
||||||
options: {ignoreFinalized?: boolean} = NO_OPTIONS,
|
options: {ignoreFinalized?: boolean} = NO_OPTIONS,
|
||||||
) {
|
) {
|
||||||
if (!options.ignoreFinalized) {
|
if (!options.ignoreFinalized) {
|
||||||
|
@ -121,7 +119,7 @@ class ResolutionResponse<TModule: {hash(): string}, TOptions> {
|
||||||
this.mocks = mocks;
|
this.mocks = mocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
getResolvedDependencyPairs(module: TModule) {
|
getResolvedDependencyPairs(module: TModule): $ReadOnlyArray<[string, TModule]> {
|
||||||
this._assertFinalized();
|
this._assertFinalized();
|
||||||
return this._mappings[module.hash()];
|
return this._mappings[module.hash()];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,35 @@
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2016-present, Facebook, Inc.
|
* Copyright (c) 2016-present, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under the BSD-style license found in the
|
* 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
|
* 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.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = function MapWithDefaults(factory, iterable) {
|
class MapWithDefaults<TK, TV> extends Map<TK, TV> {
|
||||||
// This can't be `MapWithDefaults extends Map`, b/c the way babel transforms
|
_factory: TK => TV;
|
||||||
// super calls in constructors: Map.call(this, iterable) throws for native
|
|
||||||
// Map objects in node 4+.
|
|
||||||
// TODO(davidaurelio) switch to a transform that does not transform classes
|
|
||||||
// and super calls, and change this into a class
|
|
||||||
|
|
||||||
const map = iterable ? new Map(iterable) : new Map();
|
constructor(factory: TK => TV, iterable?: Iterable<[TK, TV]>) {
|
||||||
const {get} = map;
|
super(iterable);
|
||||||
map.get = key => {
|
this._factory = factory;
|
||||||
if (map.has(key)) {
|
}
|
||||||
return get.call(map, key);
|
|
||||||
|
get(key: TK): TV {
|
||||||
|
if (this.has(key)) {
|
||||||
|
/* $FlowFixMe: can never be `undefined` since we tested with `has`
|
||||||
|
* (except if `TV` includes `void` as subtype, ex. is nullable) */
|
||||||
|
return Map.prototype.get.call(this, key);
|
||||||
}
|
}
|
||||||
|
const value = this._factory(key);
|
||||||
const value = factory(key);
|
this.set(key, value);
|
||||||
map.set(key, value);
|
|
||||||
return value;
|
return value;
|
||||||
};
|
}
|
||||||
return map;
|
}
|
||||||
};
|
|
||||||
|
module.exports = MapWithDefaults;
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
jest.disableAutomock();
|
||||||
|
|
||||||
|
const MapWithDefaults = require('../MapWithDefaults');
|
||||||
|
|
||||||
|
describe('MapWithDefaults', function() {
|
||||||
|
it('works', () => {
|
||||||
|
const map = new MapWithDefaults(() => ['bar']);
|
||||||
|
map.get('foo').push('baz');
|
||||||
|
expect(map.get('foo')).toEqual(['bar', 'baz']);
|
||||||
|
});
|
||||||
|
});
|
|
@ -17,7 +17,7 @@ import type ResolutionResponse from '../DependencyGraph/ResolutionResponse';
|
||||||
function resolveModuleRequires<TModule: {hash(): string}, TOptions>(
|
function resolveModuleRequires<TModule: {hash(): string}, TOptions>(
|
||||||
resolutionResponse: ResolutionResponse<TModule, TOptions>,
|
resolutionResponse: ResolutionResponse<TModule, TOptions>,
|
||||||
module: TModule,
|
module: TModule,
|
||||||
) {
|
): Array<TModule> {
|
||||||
const pairs = resolutionResponse.getResolvedDependencyPairs(module);
|
const pairs = resolutionResponse.getResolvedDependencyPairs(module);
|
||||||
return pairs ? pairs.map(([, dependencyModule]) => dependencyModule) : [];
|
return pairs ? pairs.map(([, dependencyModule]) => dependencyModule) : [];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue