From b6478a345823c4a744fb9ad53caa3be6da8b5bf3 Mon Sep 17 00:00:00 2001 From: Jean Lauliac Date: Thu, 8 Dec 2016 05:10:37 -0800 Subject: [PATCH] packager: Resolver&co: @flow Reviewed By: davidaurelio Differential Revision: D4285448 fbshipit-source-id: ec9bc6fd3c6d6eae89347762bff8b5b24662394b --- flow/babel.js.flow | 11 ++-- packager/react-packager/src/Bundler/index.js | 40 ++++++----- .../src/JSTransformer/worker/worker.js | 14 ++-- packager/react-packager/src/Resolver/index.js | 66 +++++++++++++++---- .../react-packager/src/lib/TransformCache.js | 5 +- .../DependencyGraph/ResolutionRequest.js | 2 +- .../DependencyGraph/ResolutionResponse.js | 11 +++- .../react-packager/src/node-haste/Module.js | 11 ++-- .../react-packager/src/node-haste/index.js | 17 ++--- 9 files changed, 122 insertions(+), 55 deletions(-) diff --git a/flow/babel.js.flow b/flow/babel.js.flow index ad97546cc..bc80b72e8 100644 --- a/flow/babel.js.flow +++ b/flow/babel.js.flow @@ -52,7 +52,7 @@ type GeneratorOptions = { type InlinePlugin = [string | {} | () => {}, any]; // based on https://babeljs.io/docs/usage/options/ -- 2016-11-11 -type _TransformOptions = { +type __TransformOptions = { filename?: string, filenameRelative?: string, presets?: Array, @@ -85,8 +85,8 @@ type _TransformOptions = { extends?: string, }; -type TransformOptions = - _TransformOptions & {env?: {[key: string]: TransformOptions}}; +type _TransformOptions = + __TransformOptions & {env?: {[key: string]: __TransformOptions}}; declare class _Ast {}; type TransformResult = { ast: _Ast, @@ -98,9 +98,10 @@ type VisitFn = (path: Object, state: State) => any; declare module 'babel-core' { declare type SourceMap = _SourceMap; declare type Ast = _Ast; + declare type TransformOptions = _TransformOptions; declare function transform( code: string, - options?: TransformOptions, + options?: _TransformOptions, ): TransformResult; declare function traverse( ast: _Ast, @@ -114,7 +115,7 @@ declare module 'babel-core' { declare function transformFromAst( ast: _Ast, code?: ?string, - babelOptions?: TransformOptions, + babelOptions?: _TransformOptions, ): TransformResult; } diff --git a/packager/react-packager/src/Bundler/index.js b/packager/react-packager/src/Bundler/index.js index f7624ad97..e8499574c 100644 --- a/packager/react-packager/src/Bundler/index.js +++ b/packager/react-packager/src/Bundler/index.js @@ -35,9 +35,10 @@ const { extname, } = require('path'); -import AssetServer from '../AssetServer'; -import Module from '../node-haste/Module'; -import ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse'; +import type AssetServer from '../AssetServer'; +import type Module from '../node-haste/Module'; +import type ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse'; +import type {Options as TransformOptions} from '../JSTransformer/worker/worker'; export type GetTransformOptions = ( string, @@ -353,8 +354,6 @@ class Bundler { ? runBeforeMainModule .map(name => modulesByName[name]) .filter(Boolean) - /* $FlowFixMe: looks like ResolutionResponse is monkey-patched - * with `getModuleId`. */ .map(response.getModuleId) : undefined; @@ -450,7 +449,8 @@ class Bundler { entryFilePath, assetPlugins, transformOptions: response.transformOptions, - getModuleId: response.getModuleId, + /* $FlowFixMe: `getModuleId` is monkey-patched */ + getModuleId: (response.getModuleId: () => number), dependencyPairs: response.getResolvedDependencyPairs(module), }).then(transformed => { modulesByName[transformed.name] = module; @@ -485,7 +485,7 @@ class Bundler { generateSourceMaps = false, }: { entryFile: string, - platform: ?string, + platform: string, dev?: boolean, minify?: boolean, hot?: boolean, @@ -528,14 +528,14 @@ class Bundler { onProgress, }: { entryFile: string, - platform: ?string, + platform: string, dev?: boolean, minify?: boolean, hot?: boolean, recursive?: boolean, generateSourceMaps?: boolean, isolateModuleIDs?: boolean, - onProgress?: () => mixed, + onProgress?: ?(finishedModules: number, totalModules: number) => mixed, }) { return this.getTransformOptions( entryFile, @@ -567,7 +567,7 @@ class Bundler { getOrderedDependencyPaths({ entryFile, dev, platform }: { entryFile: string, dev: boolean, - platform: ?string, + platform: string, }) { return this.getDependencies({entryFile, dev, platform}).then( ({ dependencies }) => { @@ -608,7 +608,15 @@ class Bundler { getModuleId, dependencyPairs, assetPlugins, - }) { + }: { + module: Module, + bundle: Bundle, + entryFilePath: string, + transformOptions: TransformOptions, + getModuleId: () => number, + dependencyPairs: Array<[mixed, {path: string}]>, + assetPlugins: Array, + }): Promise { let moduleTransport; const moduleId = getModuleId(module); @@ -670,7 +678,9 @@ class Bundler { __packager_asset: true, fileSystemLocation: pathDirname(module.path), httpServerLocation: assetUrlPath, + /* $FlowFixMe: `resolution` is assets-only */ width: dimensions ? dimensions.width / module.resolution : undefined, + /* $FlowFixMe: `resolution` is assets-only */ height: dimensions ? dimensions.height / module.resolution : undefined, scales: assetData.scales, files: assetData.files, @@ -718,9 +728,9 @@ class Bundler { } _generateAssetModule( - bundle, - module, - moduleId, + bundle: Bundle, + module: Module, + moduleId: number, assetPlugins: Array = [], platform: ?string = null, ) { @@ -745,7 +755,7 @@ class Bundler { mainModuleName: string, options: { dev?: boolean, - platform: ?string, + platform: string, hot?: boolean, generateSourceMaps?: boolean, }, diff --git a/packager/react-packager/src/JSTransformer/worker/worker.js b/packager/react-packager/src/JSTransformer/worker/worker.js index 794532188..a81edf9e1 100644 --- a/packager/react-packager/src/JSTransformer/worker/worker.js +++ b/packager/react-packager/src/JSTransformer/worker/worker.js @@ -18,7 +18,7 @@ const invariant = require('invariant'); const minify = require('./minify'); import type {LogEntry} from '../../Logger/Types'; -import type {Ast, SourceMap} from 'babel-core'; +import type {Ast, SourceMap, TransformOptions} from 'babel-core'; function makeTransformParams(filename, sourceCode, options) { if (filename.endsWith('.json')) { @@ -31,7 +31,7 @@ export type TransformedCode = { code: string, dependencies: Array, dependencyOffsets: Array, - map?: ?{}, + map?: ?SourceMap, }; type Transform = ( @@ -47,7 +47,13 @@ type Transform = ( ) => void; export type Options = { - transform?: {projectRoots: Array}, + transform: { + projectRoots: Array, + ramGroups: Array, + platform: string, + preloadedModules: Array, + } & TransformOptions, + platform: string, }; export type Data = { @@ -132,7 +138,7 @@ exports.transformAndExtractDependencies = ( transform: string, filename: string, sourceCode: string, - options: ?Options, + options: Options, callback: Callback, ) => { /* $FlowFixMe: impossible to type a dynamic require */ diff --git a/packager/react-packager/src/Resolver/index.js b/packager/react-packager/src/Resolver/index.js index 68fb11883..87e23493a 100644 --- a/packager/react-packager/src/Resolver/index.js +++ b/packager/react-packager/src/Resolver/index.js @@ -5,9 +5,11 @@ * 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'; +'use strict'; const DependencyGraph = require('../node-haste'); @@ -15,6 +17,11 @@ const declareOpts = require('../lib/declareOpts'); const defaults = require('../../../defaults'); const pathJoin = require('path').join; +import type ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse'; +import type Module from '../node-haste/Module'; +import type {SourceMap} from '../lib/SourceMap'; +import type {Options as TransformOptions} from '../JSTransformer/worker/worker'; + const validateOpts = declareOpts({ projectRoots: { type: 'array', @@ -87,7 +94,12 @@ const getDependenciesValidateOpts = declareOpts({ class Resolver { - constructor(options) { + _depGraph: DependencyGraph; + _minifyCode: (filePath: string, code: string, map: SourceMap) => + Promise<{code: string, map: SourceMap}>; + _polyfillModuleNames: Array; + + constructor(options: {resetCache: boolean}) { const opts = validateOpts(options); this._depGraph = new DependencyGraph({ @@ -122,15 +134,24 @@ class Resolver { }); } - getShallowDependencies(entryFile, transformOptions) { + getShallowDependencies( + entryFile: string, + transformOptions: TransformOptions, + ): Array { return this._depGraph.getShallowDependencies(entryFile, transformOptions); } - getModuleForPath(entryFile) { + getModuleForPath(entryFile: string): Module { return this._depGraph.getModuleForPath(entryFile); } - getDependencies(entryPath, options, transformOptions, onProgress, getModuleId) { + getDependencies( + entryPath: string, + options: {}, + transformOptions: TransformOptions, + onProgress?: ?(finishedModules: number, totalModules: number) => mixed, + getModuleId: mixed, + ): Promise { const {platform, recursive} = getDependenciesValidateOpts(options); return this._depGraph.getDependencies({ entryPath, @@ -148,7 +169,7 @@ class Resolver { }); } - getModuleSystemDependencies(options) { + getModuleSystemDependencies(options: {}): Array { const opts = getDependenciesValidateOpts(options); const prelude = opts.dev @@ -167,7 +188,7 @@ class Resolver { })); } - _getPolyfillDependencies() { + _getPolyfillDependencies(): Array { const polyfillModuleNames = defaults.polyfills.concat(this._polyfillModuleNames); return polyfillModuleNames.map( @@ -179,7 +200,12 @@ class Resolver { ); } - resolveRequires(resolutionResponse, module, code, dependencyOffsets = []) { + resolveRequires( + resolutionResponse: ResolutionResponse, + module: Module, + code: string, + dependencyOffsets: Array = [], + ): string { const resolvedDeps = Object.create(null); // here, we build a map of all require strings (relative and absolute) @@ -187,6 +213,7 @@ class Resolver { resolutionResponse.getResolvedDependencyPairs(module) .forEach(([depName, depModule]) => { if (depModule) { + /* $FlowFixMe: `getModuleId` is monkey-patched so may not exist */ resolvedDeps[depName] = resolutionResponse.getModuleId(depModule); } }); @@ -204,7 +231,7 @@ class Resolver { ? `${JSON.stringify(resolvedDeps[depName])} /* ${depName} */` : codeMatch; - code = dependencyOffsets.reduceRight((codeBits, offset) => { + const codeParts = dependencyOffsets.reduceRight((codeBits, offset) => { const first = codeBits.shift(); codeBits.unshift( first.slice(0, offset), @@ -213,7 +240,7 @@ class Resolver { return codeBits; }, [code]); - return code.join(''); + return codeParts.join(''); } wrapModule({ @@ -225,6 +252,17 @@ class Resolver { meta = {}, dev = true, minify = false, + }: { + resolutionResponse: ResolutionResponse, + module: Module, + name: string, + map: SourceMap, + code: string, + meta?: { + dependencyOffsets?: Array, + }, + dev?: boolean, + minify?: boolean, }) { if (module.isJSON()) { code = `module.exports = ${code}`; @@ -233,6 +271,7 @@ class Resolver { if (module.isPolyfill()) { code = definePolyfillCode(code); } else { + /* $FlowFixMe: `getModuleId` is monkey-patched so may not exist */ const moduleId = resolutionResponse.getModuleId(module); code = this.resolveRequires( resolutionResponse, @@ -243,17 +282,18 @@ class Resolver { code = defineModuleCode(moduleId, code, name, dev); } - return minify ? this._minifyCode(module.path, code, map) : Promise.resolve({code, map}); } - minifyModule({path, code, map}) { + minifyModule( + {path, code, map}: {path: string, code: string, map: SourceMap}, + ): Promise<{code: string, map: SourceMap}> { return this._minifyCode(path, code, map); } - getDependencyGraph() { + getDependencyGraph(): DependencyGraph { return this._depGraph; } } diff --git a/packager/react-packager/src/lib/TransformCache.js b/packager/react-packager/src/lib/TransformCache.js index 69f48584c..b6638f75b 100644 --- a/packager/react-packager/src/lib/TransformCache.js +++ b/packager/react-packager/src/lib/TransformCache.js @@ -29,6 +29,7 @@ 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'; /** * If packager is running for two different directories, we don't want the @@ -79,7 +80,7 @@ export type CachedResult = { code: string, dependencies: Array, dependencyOffsets: Array, - map?: ?{}, + map?: ?SourceMap, }; /** @@ -227,7 +228,7 @@ function readMetadataFileSync( cachedSourceHash: number, dependencies: Array, dependencyOffsets: Array, - sourceMap: ?{}, + sourceMap: ?SourceMap, } { const metadataStr = fs.readFileSync(metadataFilePath, 'utf8'); let metadata; diff --git a/packager/react-packager/src/node-haste/DependencyGraph/ResolutionRequest.js b/packager/react-packager/src/node-haste/DependencyGraph/ResolutionRequest.js index e3b5cdfaa..52a892935 100644 --- a/packager/react-packager/src/node-haste/DependencyGraph/ResolutionRequest.js +++ b/packager/react-packager/src/node-haste/DependencyGraph/ResolutionRequest.js @@ -124,7 +124,7 @@ class ResolutionRequest { }: { response: ResolutionResponse, transformOptions: Object, - onProgress: () => void, + onProgress?: ?(finishedModules: number, totalModules: number) => mixed, recursive: boolean, }) { const entry = this._moduleCache.getModule(this._entryPath); diff --git a/packager/react-packager/src/node-haste/DependencyGraph/ResolutionResponse.js b/packager/react-packager/src/node-haste/DependencyGraph/ResolutionResponse.js index 63ce48ef7..8ed5d91f1 100644 --- a/packager/react-packager/src/node-haste/DependencyGraph/ResolutionResponse.js +++ b/packager/react-packager/src/node-haste/DependencyGraph/ResolutionResponse.js @@ -13,21 +13,26 @@ import Module from '../Module'; +import type {Options as TransformOptions} from '../../JSTransformer/worker/worker'; + const NO_OPTIONS = {}; class ResolutionResponse { - transformOptions: {}; + transformOptions: TransformOptions; dependencies: Array; mainModuleId: ?(number | string); mocks: mixed; numPrependedDependencies: number; + // This is monkey-patched from Resolver. + getModuleId: ?() => number; + _mappings: {}; _finalized: boolean; _mainModule: ?Module; - constructor({transformOptions}: {transformOptions: {}}) { + constructor({transformOptions}: {transformOptions: TransformOptions}) { this.transformOptions = transformOptions; this.dependencies = []; this.mainModuleId = null; @@ -76,7 +81,7 @@ class ResolutionResponse { } } - finalize() { + finalize(): ResolutionResponse { /* $FlowFixMe: _mainModule is not initialized in the constructor. */ return this._mainModule.getName().then(id => { this.mainModuleId = id; diff --git a/packager/react-packager/src/node-haste/Module.js b/packager/react-packager/src/node-haste/Module.js index acdb5c117..0435843f0 100644 --- a/packager/react-packager/src/node-haste/Module.js +++ b/packager/react-packager/src/node-haste/Module.js @@ -25,16 +25,18 @@ const jsonStableStringify = require('json-stable-stringify'); const {join: joinPath, relative: relativePath, extname} = require('path'); import type {TransformedCode, Options as TransformOptions} from '../JSTransformer/worker/worker'; +import type {SourceMap} from '../lib/SourceMap'; import type {ReadTransformProps} from '../lib/TransformCache'; import type Cache from './Cache'; import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers'; import type ModuleCache from './ModuleCache'; type ReadResult = { - code?: string, + code: string, dependencies?: ?Array, dependencyOffsets?: ?Array, - map?: ?{}, + map?: ?SourceMap, + source: string, }; export type TransformCode = ( @@ -122,7 +124,7 @@ class Module { return this.read(transformOptions).then(({map}) => map); } - getName(): Promise { + getName(): Promise { return this._cache.get( this.path, 'name', @@ -209,9 +211,10 @@ class Module { id?: string, extern: boolean, result: TransformedCode, - ) { + ): ReadResult { if (this._options.cacheTransformResults === false) { const {dependencies} = result; + /* $FlowFixMe: this code path is dead, remove. */ return {dependencies}; } return {...result, id, source}; diff --git a/packager/react-packager/src/node-haste/index.js b/packager/react-packager/src/node-haste/index.js index 3667077d9..4595d1557 100644 --- a/packager/react-packager/src/node-haste/index.js +++ b/packager/react-packager/src/node-haste/index.js @@ -38,6 +38,7 @@ const { print, } = require('../Logger'); +import type {Options as TransformOptions} from '../JSTransformer/worker/worker'; import type { Options as ModuleOptions, TransformCode, @@ -53,7 +54,7 @@ class DependencyGraph { extraNodeModules: Object, forceNodeFilesystemAPI: boolean, ignoreFilePath: (filePath: string) => boolean, - maxWorkers: number, + maxWorkers: ?number, mocksPattern: mixed, moduleOptions: ModuleOptions, platforms: Set, @@ -103,22 +104,22 @@ class DependencyGraph { assetDependencies: mixed, assetExts: Array, cache: Cache, - extensions: Array, + extensions?: ?Array, extraNodeModules: Object, forceNodeFilesystemAPI?: boolean, ignoreFilePath: (filePath: string) => boolean, - maxWorkers: number, - mocksPattern: mixed, + maxWorkers?: ?number, + mocksPattern?: mixed, moduleOptions: ?ModuleOptions, platforms: mixed, preferNativePlatform: boolean, providesModuleNodeModules: Array, resetCache: boolean, roots: Array, - shouldThrowOnUnresolvedErrors: () => boolean, + shouldThrowOnUnresolvedErrors?: () => boolean, transformCacheKey: string, transformCode: TransformCode, - useWatchman: boolean, + useWatchman?: ?boolean, watch: boolean, }) { this._opts = { @@ -272,8 +273,8 @@ class DependencyGraph { }: { entryPath: string, platform: string, - transformOptions: {}, - onProgress: () => void, + transformOptions: TransformOptions, + onProgress?: ?(finishedModules: number, totalModules: number) => mixed, recursive: boolean, }) { return this.load().then(() => {