2015-11-04 16:04:44 -08:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
2015-11-09 13:32:42 -08:00
|
|
|
const path = require('path');
|
|
|
|
const Activity = require('../Activity');
|
|
|
|
const DependencyGraph = require('../DependencyResolver/DependencyGraph');
|
2015-11-16 22:48:28 -08:00
|
|
|
const replacePatterns = require('../DependencyResolver/lib/replacePatterns');
|
2015-11-09 13:32:42 -08:00
|
|
|
const Polyfill = require('../DependencyResolver/Polyfill');
|
|
|
|
const declareOpts = require('../lib/declareOpts');
|
|
|
|
const Promise = require('promise');
|
|
|
|
|
|
|
|
const validateOpts = declareOpts({
|
2015-11-04 16:04:44 -08:00
|
|
|
projectRoots: {
|
|
|
|
type: 'array',
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
blacklistRE: {
|
|
|
|
type: 'object', // typeof regex is object
|
|
|
|
},
|
|
|
|
polyfillModuleNames: {
|
|
|
|
type: 'array',
|
|
|
|
default: [],
|
|
|
|
},
|
|
|
|
moduleFormat: {
|
|
|
|
type: 'string',
|
|
|
|
default: 'haste',
|
|
|
|
},
|
|
|
|
assetRoots: {
|
|
|
|
type: 'array',
|
|
|
|
default: [],
|
|
|
|
},
|
|
|
|
fileWatcher: {
|
|
|
|
type: 'object',
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
assetExts: {
|
|
|
|
type: 'array',
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
cache: {
|
|
|
|
type: 'object',
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2015-11-09 13:32:42 -08:00
|
|
|
const getDependenciesValidateOpts = declareOpts({
|
2015-11-04 16:04:44 -08:00
|
|
|
dev: {
|
|
|
|
type: 'boolean',
|
|
|
|
default: true,
|
|
|
|
},
|
|
|
|
platform: {
|
|
|
|
type: 'string',
|
|
|
|
required: false,
|
|
|
|
},
|
2015-12-01 07:42:44 -08:00
|
|
|
isUnbundle: {
|
|
|
|
type: 'boolean',
|
|
|
|
default: false
|
|
|
|
},
|
2015-11-04 16:04:44 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
class Resolver {
|
|
|
|
|
|
|
|
constructor(options) {
|
2015-11-09 13:32:42 -08:00
|
|
|
const opts = validateOpts(options);
|
2015-11-04 16:04:44 -08:00
|
|
|
|
|
|
|
this._depGraph = new DependencyGraph({
|
2015-11-09 13:32:42 -08:00
|
|
|
activity: Activity,
|
2015-11-04 16:04:44 -08:00
|
|
|
roots: opts.projectRoots,
|
|
|
|
assetRoots_DEPRECATED: opts.assetRoots,
|
|
|
|
assetExts: opts.assetExts,
|
|
|
|
ignoreFilePath: function(filepath) {
|
|
|
|
return filepath.indexOf('__tests__') !== -1 ||
|
|
|
|
(opts.blacklistRE && opts.blacklistRE.test(filepath));
|
|
|
|
},
|
2015-11-09 13:32:46 -08:00
|
|
|
providesModuleNodeModules: [
|
2015-12-30 11:38:44 -08:00
|
|
|
'fbjs',
|
|
|
|
'react',
|
2015-11-09 13:32:46 -08:00
|
|
|
'react-native',
|
|
|
|
// Parse requires AsyncStorage. They will
|
|
|
|
// change that to require('react-native') which
|
|
|
|
// should work after this release and we can
|
|
|
|
// remove it from here.
|
|
|
|
'parse',
|
2015-12-28 16:43:21 -08:00
|
|
|
'react-transform-hmr',
|
2015-11-09 13:32:46 -08:00
|
|
|
],
|
|
|
|
platforms: ['ios', 'android'],
|
2015-12-30 11:38:44 -08:00
|
|
|
preferNativePlatform: true,
|
2015-11-04 16:04:44 -08:00
|
|
|
fileWatcher: opts.fileWatcher,
|
|
|
|
cache: opts.cache,
|
|
|
|
});
|
|
|
|
|
|
|
|
this._polyfillModuleNames = opts.polyfillModuleNames || [];
|
|
|
|
}
|
|
|
|
|
2015-12-29 18:24:08 -08:00
|
|
|
getShallowDependencies(entryFile) {
|
|
|
|
return this._depGraph.getShallowDependencies(entryFile);
|
|
|
|
}
|
|
|
|
|
2016-01-04 13:01:28 -08:00
|
|
|
getModuleForPath(entryFile) {
|
|
|
|
return this._depGraph.getModuleForPath(entryFile);
|
|
|
|
}
|
|
|
|
|
2015-11-04 16:04:44 -08:00
|
|
|
getDependencies(main, options) {
|
2015-11-09 13:32:42 -08:00
|
|
|
const opts = getDependenciesValidateOpts(options);
|
2015-11-04 16:04:44 -08:00
|
|
|
|
|
|
|
return this._depGraph.getDependencies(main, opts.platform).then(
|
|
|
|
resolutionResponse => {
|
2015-11-25 17:34:55 -08:00
|
|
|
this._getPolyfillDependencies().reverse().forEach(
|
2015-11-04 16:04:44 -08:00
|
|
|
polyfill => resolutionResponse.prependDependency(polyfill)
|
|
|
|
);
|
|
|
|
|
|
|
|
return resolutionResponse.finalize();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-11-25 17:34:55 -08:00
|
|
|
getModuleSystemDependencies(options) {
|
|
|
|
const opts = getDependenciesValidateOpts(options);
|
|
|
|
|
|
|
|
const prelude = opts.dev
|
2015-11-04 16:04:44 -08:00
|
|
|
? path.join(__dirname, 'polyfills/prelude_dev.js')
|
2015-11-25 17:34:55 -08:00
|
|
|
: path.join(__dirname, 'polyfills/prelude.js');
|
|
|
|
|
2015-12-01 07:42:44 -08:00
|
|
|
const moduleSystem = opts.isUnbundle
|
|
|
|
? path.join(__dirname, 'polyfills/require-unbundle.js')
|
|
|
|
: path.join(__dirname, 'polyfills/require.js');
|
2015-11-25 17:34:55 -08:00
|
|
|
|
|
|
|
return [
|
|
|
|
prelude,
|
|
|
|
moduleSystem
|
|
|
|
].map(moduleName => new Polyfill({
|
|
|
|
path: moduleName,
|
|
|
|
id: moduleName,
|
|
|
|
dependencies: [],
|
|
|
|
isPolyfill: true,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
_getPolyfillDependencies() {
|
|
|
|
const polyfillModuleNames = [
|
2015-11-04 16:04:44 -08:00
|
|
|
path.join(__dirname, 'polyfills/polyfills.js'),
|
|
|
|
path.join(__dirname, 'polyfills/console.js'),
|
|
|
|
path.join(__dirname, 'polyfills/error-guard.js'),
|
|
|
|
path.join(__dirname, 'polyfills/String.prototype.es6.js'),
|
|
|
|
path.join(__dirname, 'polyfills/Array.prototype.es6.js'),
|
2015-11-06 17:19:55 -08:00
|
|
|
path.join(__dirname, 'polyfills/Array.es6.js'),
|
2015-11-11 22:53:04 -08:00
|
|
|
path.join(__dirname, 'polyfills/babelHelpers.js'),
|
2015-11-04 16:04:44 -08:00
|
|
|
].concat(this._polyfillModuleNames);
|
|
|
|
|
|
|
|
return polyfillModuleNames.map(
|
|
|
|
(polyfillModuleName, idx) => new Polyfill({
|
|
|
|
path: polyfillModuleName,
|
|
|
|
id: polyfillModuleName,
|
|
|
|
dependencies: polyfillModuleNames.slice(0, idx),
|
|
|
|
isPolyfill: true,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-01-06 09:46:56 -08:00
|
|
|
resolveRequires(resolutionResponse, module, code) {
|
2015-11-04 16:04:44 -08:00
|
|
|
return Promise.resolve().then(() => {
|
|
|
|
if (module.isPolyfill()) {
|
2015-12-01 07:42:44 -08:00
|
|
|
return Promise.resolve({code});
|
2015-11-04 16:04:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
const resolvedDeps = Object.create(null);
|
|
|
|
const resolvedDepsArr = [];
|
|
|
|
|
|
|
|
return Promise.all(
|
|
|
|
resolutionResponse.getResolvedDependencyPairs(module).map(
|
|
|
|
([depName, depModule]) => {
|
|
|
|
if (depModule) {
|
|
|
|
return depModule.getName().then(name => {
|
|
|
|
resolvedDeps[depName] = name;
|
|
|
|
resolvedDepsArr.push(name);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
).then(() => {
|
|
|
|
const relativizeCode = (codeMatch, pre, quot, depName, post) => {
|
|
|
|
const depId = resolvedDeps[depName];
|
|
|
|
if (depId) {
|
|
|
|
return pre + quot + depId + post;
|
|
|
|
} else {
|
|
|
|
return codeMatch;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-12-01 07:42:44 -08:00
|
|
|
code = code
|
|
|
|
.replace(replacePatterns.IMPORT_RE, relativizeCode)
|
|
|
|
.replace(replacePatterns.EXPORT_RE, relativizeCode)
|
|
|
|
.replace(replacePatterns.REQUIRE_RE, relativizeCode);
|
|
|
|
|
2016-01-06 09:46:56 -08:00
|
|
|
return module.getName().then(name => {
|
|
|
|
return {name, code};
|
|
|
|
});
|
2015-11-04 16:04:44 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-01-06 09:46:56 -08:00
|
|
|
wrapModule(resolutionResponse, module, code) {
|
|
|
|
if (module.isPolyfill()) {
|
|
|
|
return Promise.resolve({code});
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.resolveRequires(resolutionResponse, module, code).then(
|
|
|
|
({name, code}) => {
|
|
|
|
return {name, code: defineModuleCode(name, code)};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-11-04 16:04:44 -08:00
|
|
|
getDebugInfo() {
|
|
|
|
return this._depGraph.getDebugInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-12-01 07:42:44 -08:00
|
|
|
function defineModuleCode(moduleName, code) {
|
2015-11-04 16:04:44 -08:00
|
|
|
return [
|
|
|
|
`__d(`,
|
|
|
|
`'${moduleName}',`,
|
|
|
|
'function(global, require, module, exports) {',
|
|
|
|
` ${code}`,
|
|
|
|
'\n});',
|
|
|
|
].join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = Resolver;
|