Skip to content

Commit

Permalink
Introduce HasteImpl
Browse files Browse the repository at this point in the history
Summary:
Similar to jestjs/jest#2877, this introduces an optional config `HasteImpl` of type `{getHasteName(filePath: string): (string|void)}` that returns the haste name for a module at filePath if it is a haste module or undefined otherwise.

This allows us to inject a custom implementation of haste's module id resolution rather than only relying on `providesModule` annotations

Reviewed By: davidaurelio

Differential Revision: D4589372

fbshipit-source-id: 4d1983dfbf09c9d67faf725e86ae86ab42433b7d
  • Loading branch information
voideanvalue authored and facebook-github-bot committed Feb 27, 2017
1 parent 4ba9834 commit 234f4f5
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 18 deletions.
1 change: 1 addition & 0 deletions local-cli/bundle/buildBundle.js
Expand Up @@ -76,6 +76,7 @@ function buildBundle(
extraNodeModules: config.extraNodeModules,
getTransformOptions: config.getTransformOptions,
globalTransformCache: null,
hasteImpl: config.hasteImpl,
platforms: defaultPlatforms.concat(platforms),
projectRoots: config.getProjectRoots(),
providesModuleNodeModules: providesModuleNodeModules,
Expand Down
8 changes: 8 additions & 0 deletions local-cli/core/index.js
Expand Up @@ -16,6 +16,7 @@ const defaultConfig = require('./default.config');
const minimist = require('minimist');

import type {GetTransformOptions} from '../../packager/src/Bundler';
import type {HasteImpl} from '../../packager/src/node-haste/Module';
import type {CommandT} from '../commands';

/**
Expand Down Expand Up @@ -66,6 +67,13 @@ export type ConfigT = {
* Returns dependency config from <node_modules>/packageName
*/
getDependencyConfig(pkgName: string): Object,

/**
* A module that exports:
* - a `getHasteName(filePath)` method that returns `hasteName` for module at
* `filePath`, or undefined if `filePath` is not a haste module.
*/
hasteImpl?: HasteImpl,
};

/**
Expand Down
1 change: 1 addition & 0 deletions local-cli/dependencies/dependencies.js
Expand Up @@ -29,6 +29,7 @@ function dependencies(argv, config, args, packagerInstance) {
projectRoots: config.getProjectRoots(),
blacklistRE: config.getBlacklistRE(),
getTransformOptions: config.getTransformOptions,
hasteImpl: config.hasteImpl,
transformModulePath: transformModulePath,
extraNodeModules: config.extraNodeModules,
verbose: config.verbose,
Expand Down
1 change: 1 addition & 0 deletions local-cli/server/runServer.js
Expand Up @@ -94,6 +94,7 @@ function getPackagerServer(args, config) {
cacheVersion: '3',
extraNodeModules: config.extraNodeModules,
getTransformOptions: config.getTransformOptions,
hasteImpl: config.hasteImpl,
platforms: defaultPlatforms.concat(args.platforms),
projectRoots: args.projectRoots,
providesModuleNodeModules: providesModuleNodeModules,
Expand Down
3 changes: 3 additions & 0 deletions packager/react-packager.js
Expand Up @@ -18,11 +18,13 @@ const invariant = require('fbjs/lib/invariant');

import type GlobalTransformCache from './src/lib/GlobalTransformCache';
import type {Reporter} from './src/lib/reporting';
import type {HasteImpl} from './src/node-haste/Module';

exports.createServer = createServer;
exports.Logger = Logger;

type Options = {
hasteImpl?: HasteImpl,
globalTransformCache: ?GlobalTransformCache,
nonPersistent?: boolean,
projectRoots: Array<string>,
Expand All @@ -31,6 +33,7 @@ type Options = {
};

type StrictOptions = {
hasteImpl?: HasteImpl,
globalTransformCache: ?GlobalTransformCache,
nonPersistent?: boolean,
projectRoots: Array<string>,
Expand Down
4 changes: 3 additions & 1 deletion packager/src/Bundler/index.js
Expand Up @@ -36,7 +36,7 @@ const {
const VERSION = require('../../package.json').version;

import type AssetServer from '../AssetServer';
import type Module from '../node-haste/Module';
import type Module, {HasteImpl} from '../node-haste/Module';
import type ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse';
import type {Options as JSTransformerOptions, TransformOptions} from '../JSTransformer/worker/worker';
import type {Reporter} from '../lib/reporting';
Expand Down Expand Up @@ -86,6 +86,7 @@ type Options = {
extraNodeModules: {},
getTransformOptions?: GetTransformOptions,
globalTransformCache: ?GlobalTransformCache,
hasteImpl?: HasteImpl,
moduleFormat: string,
platforms: Array<string>,
polyfillModuleNames: Array<string>,
Expand Down Expand Up @@ -172,6 +173,7 @@ class Bundler {
extraNodeModules: opts.extraNodeModules,
getTransformCacheKey,
globalTransformCache: opts.globalTransformCache,
hasteImpl: opts.hasteImpl,
minifyCode: this._transformer.minify,
moduleFormat: opts.moduleFormat,
platforms: opts.platforms,
Expand Down
4 changes: 3 additions & 1 deletion packager/src/Resolver/index.js
Expand Up @@ -17,7 +17,7 @@ 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 Module, {HasteImpl} from '../node-haste/Module';
import type {SourceMap} from '../lib/SourceMap';
import type {Options as TransformOptions} from '../JSTransformer/worker/worker';
import type {Reporter} from '../lib/reporting';
Expand All @@ -36,6 +36,7 @@ type Options = {
extraNodeModules?: {},
getTransformCacheKey: GetTransformCacheKey,
globalTransformCache: ?GlobalTransformCache,
hasteImpl?: HasteImpl,
minifyCode: MinifyCode,
platforms: Array<string>,
polyfillModuleNames?: Array<string>,
Expand Down Expand Up @@ -70,6 +71,7 @@ class Resolver {
maxWorkers: null,
moduleOptions: {
cacheTransformResults: true,
hasteImpl: opts.hasteImpl,
resetCache: opts.resetCache,
},
platforms: new Set(opts.platforms),
Expand Down
5 changes: 4 additions & 1 deletion packager/src/Server/index.js
Expand Up @@ -26,7 +26,7 @@ const url = require('url');

const debug = require('debug')('RNP:Server');

import type Module from '../node-haste/Module';
import type Module, {HasteImpl} from '../node-haste/Module';
import type {Stats} from 'fs';
import type {IncomingMessage, ServerResponse} from 'http';
import type ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse';
Expand Down Expand Up @@ -62,6 +62,7 @@ type Options = {
extraNodeModules?: {},
getTransformOptions?: GetTransformOptions,
globalTransformCache: ?GlobalTransformCache,
hasteImpl?: HasteImpl,
moduleFormat?: string,
platforms?: Array<string>,
polyfillModuleNames?: Array<string>,
Expand Down Expand Up @@ -178,6 +179,7 @@ class Server {
cacheVersion: string,
extraNodeModules: {},
getTransformOptions?: GetTransformOptions,
hasteImpl?: HasteImpl,
moduleFormat: string,
platforms: Array<string>,
polyfillModuleNames: Array<string>,
Expand Down Expand Up @@ -212,6 +214,7 @@ class Server {
extraNodeModules: options.extraNodeModules || {},
getTransformOptions: options.getTransformOptions,
globalTransformCache: options.globalTransformCache,
hasteImpl: options.hasteImpl,
moduleFormat: options.moduleFormat != null ? options.moduleFormat : 'haste',
platforms: options.platforms || defaults.platforms,
polyfillModuleNames: options.polyfillModuleNames || [],
Expand Down
66 changes: 51 additions & 15 deletions packager/src/node-haste/Module.js
Expand Up @@ -46,9 +46,20 @@ export type TransformCode = (
transformOptions: TransformOptions,
) => Promise<TransformedCode>;

export type HasteImpl = {
getHasteName(filePath: string): (string | void),
// This exists temporarily to enforce consistency while we deprecate
// @providesModule.
enforceHasteNameMatches?: (
filePath: string,
expectedName: (string | void),
) => void,
};

export type Options = {
resetCache?: boolean,
cacheTransformResults?: boolean,
hasteImpl?: HasteImpl,
resetCache?: boolean,
};

export type ConstructorArgs = {
Expand Down Expand Up @@ -191,21 +202,46 @@ class Module {
return this._docBlock;
}

_getHasteName() {
_getHasteName(): Promise<string | void> {
if (!this._hasteName) {
// Extract an id for the module if it's using @providesModule syntax
// and if it's NOT in node_modules (and not a whitelisted node_module).
// This handles the case where a project may have a dep that has @providesModule
// docblock comments, but doesn't want it to conflict with whitelisted @providesModule
// modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
// project-specific code that is using @providesModule.
this._hasteName = this._readDocBlock().then(moduleDocBlock => {
const {providesModule} = moduleDocBlock;
return providesModule
&& !this._depGraphHelpers.isNodeModulesDir(this.path)
? /^\S+/.exec(providesModule)[0]
: undefined;
});
const hasteImpl = this._options.hasteImpl;
if (hasteImpl === undefined || hasteImpl.enforceHasteNameMatches) {
this._hasteName = this._readDocBlock().then(moduleDocBlock => {
const {providesModule} = moduleDocBlock;
return providesModule
&& !this._depGraphHelpers.isNodeModulesDir(this.path)
? /^\S+/.exec(providesModule)[0]
: undefined;
});
}
if (hasteImpl !== undefined) {
const {enforceHasteNameMatches} = hasteImpl;
if (enforceHasteNameMatches) {
this._hasteName = this._hasteName.then(providesModule => {
enforceHasteNameMatches(
this.path,
providesModule,
);
return hasteImpl.getHasteName(this.path);
});
} else {
this._hasteName = Promise.resolve(hasteImpl.getHasteName(this.path));
}
} else {
// Extract an id for the module if it's using @providesModule syntax
// and if it's NOT in node_modules (and not a whitelisted node_module).
// This handles the case where a project may have a dep that has @providesModule
// docblock comments, but doesn't want it to conflict with whitelisted @providesModule
// modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
// project-specific code that is using @providesModule.
this._hasteName = this._readDocBlock().then(moduleDocBlock => {
const {providesModule} = moduleDocBlock;
return providesModule
&& !this._depGraphHelpers.isNodeModulesDir(this.path)
? /^\S+/.exec(providesModule)[0]
: undefined;
});
}
}
return this._hasteName;
}
Expand Down

0 comments on commit 234f4f5

Please sign in to comment.