PageRenderTime 53ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/packager/react-packager/src/Resolver/index.js

https://gitlab.com/18runt88/react-native-desktop
JavaScript | 288 lines | 236 code | 30 blank | 22 comment | 7 complexity | 09faf15cc8af564a39ab0f6c7a77e2fa MD5 | raw file
  1. /**
  2. * Copyright (c) 2015-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. */
  9. 'use strict';
  10. const path = require('path');
  11. const Activity = require('../Activity');
  12. const DependencyGraph = require('node-haste');
  13. const declareOpts = require('../lib/declareOpts');
  14. const Promise = require('promise');
  15. const validateOpts = declareOpts({
  16. projectRoots: {
  17. type: 'array',
  18. required: true,
  19. },
  20. blacklistRE: {
  21. type: 'object', // typeof regex is object
  22. },
  23. polyfillModuleNames: {
  24. type: 'array',
  25. default: [],
  26. },
  27. moduleFormat: {
  28. type: 'string',
  29. default: 'haste',
  30. },
  31. assetRoots: {
  32. type: 'array',
  33. default: [],
  34. },
  35. fileWatcher: {
  36. type: 'object',
  37. required: true,
  38. },
  39. assetExts: {
  40. type: 'array',
  41. required: true,
  42. },
  43. cache: {
  44. type: 'object',
  45. required: true,
  46. },
  47. transformCode: {
  48. type: 'function',
  49. },
  50. minifyCode: {
  51. type: 'function',
  52. },
  53. });
  54. const getDependenciesValidateOpts = declareOpts({
  55. dev: {
  56. type: 'boolean',
  57. default: true,
  58. },
  59. platform: {
  60. type: 'string',
  61. required: false,
  62. },
  63. unbundle: {
  64. type: 'boolean',
  65. default: false
  66. },
  67. recursive: {
  68. type: 'boolean',
  69. default: true,
  70. },
  71. });
  72. class Resolver {
  73. constructor(options) {
  74. const opts = validateOpts(options);
  75. this._depGraph = new DependencyGraph({
  76. activity: Activity,
  77. roots: opts.projectRoots,
  78. assetRoots_DEPRECATED: opts.assetRoots,
  79. assetExts: opts.assetExts,
  80. ignoreFilePath: function(filepath) {
  81. return filepath.indexOf('__tests__') !== -1 ||
  82. (opts.blacklistRE && opts.blacklistRE.test(filepath));
  83. },
  84. providesModuleNodeModules: [
  85. 'react',
  86. 'react-native',
  87. 'react-native-desktop',
  88. // Parse requires AsyncStorage. They will
  89. // change that to require('react-native') which
  90. // should work after this release and we can
  91. // remove it from here.
  92. 'parse',
  93. ],
  94. platforms: ['ios', 'android', 'osx'],
  95. preferNativePlatform: true,
  96. fileWatcher: opts.fileWatcher,
  97. cache: opts.cache,
  98. shouldThrowOnUnresolvedErrors: (_, platform) => (platform === 'ios' || platform === 'osx'),
  99. transformCode: opts.transformCode,
  100. });
  101. this._minifyCode = opts.minifyCode;
  102. this._polyfillModuleNames = opts.polyfillModuleNames || [];
  103. this._depGraph.load().catch(err => {
  104. console.error(err.message + '\n' + err.stack);
  105. process.exit(1);
  106. });
  107. }
  108. getShallowDependencies(entryFile) {
  109. return this._depGraph.getShallowDependencies(entryFile);
  110. }
  111. stat(filePath) {
  112. return this._depGraph.getFS().stat(filePath);
  113. }
  114. getModuleForPath(entryFile) {
  115. return this._depGraph.getModuleForPath(entryFile);
  116. }
  117. getDependencies(entryPath, options, transformOptions, onProgress) {
  118. const {platform, recursive} = getDependenciesValidateOpts(options);
  119. return this._depGraph.getDependencies({
  120. entryPath,
  121. platform,
  122. transformOptions,
  123. recursive,
  124. onProgress,
  125. }).then(resolutionResponse => {
  126. this._getPolyfillDependencies().reverse().forEach(
  127. polyfill => resolutionResponse.prependDependency(polyfill)
  128. );
  129. return resolutionResponse.finalize();
  130. });
  131. }
  132. getModuleSystemDependencies(options) {
  133. const opts = getDependenciesValidateOpts(options);
  134. const prelude = opts.dev
  135. ? path.join(__dirname, 'polyfills/prelude_dev.js')
  136. : path.join(__dirname, 'polyfills/prelude.js');
  137. const moduleSystem = opts.unbundle
  138. ? path.join(__dirname, 'polyfills/require-unbundle.js')
  139. : path.join(__dirname, 'polyfills/require.js');
  140. return [
  141. prelude,
  142. moduleSystem
  143. ].map(moduleName => this._depGraph.createPolyfill({
  144. file: moduleName,
  145. id: moduleName,
  146. dependencies: [],
  147. }));
  148. }
  149. _getPolyfillDependencies() {
  150. const polyfillModuleNames = [
  151. path.join(__dirname, 'polyfills/polyfills.js'),
  152. path.join(__dirname, 'polyfills/console.js'),
  153. path.join(__dirname, 'polyfills/error-guard.js'),
  154. path.join(__dirname, 'polyfills/String.prototype.es6.js'),
  155. path.join(__dirname, 'polyfills/Array.prototype.es6.js'),
  156. path.join(__dirname, 'polyfills/Array.es6.js'),
  157. path.join(__dirname, 'polyfills/Object.es7.js'),
  158. path.join(__dirname, 'polyfills/babelHelpers.js'),
  159. ].concat(this._polyfillModuleNames);
  160. return polyfillModuleNames.map(
  161. (polyfillModuleName, idx) => this._depGraph.createPolyfill({
  162. file: polyfillModuleName,
  163. id: polyfillModuleName,
  164. dependencies: polyfillModuleNames.slice(0, idx),
  165. })
  166. );
  167. }
  168. resolveRequires(resolutionResponse, module, code, dependencyOffsets = []) {
  169. return Promise.resolve().then(() => {
  170. const resolvedDeps = Object.create(null);
  171. const resolvedDepsArr = [];
  172. return Promise.all(
  173. // here, we build a map of all require strings (relative and absolute)
  174. // to the canonical name of the module they reference
  175. resolutionResponse.getResolvedDependencyPairs(module).map(
  176. ([depName, depModule]) => {
  177. if (depModule) {
  178. return depModule.getName().then(name => {
  179. resolvedDeps[depName] = name;
  180. resolvedDepsArr.push(name);
  181. });
  182. }
  183. }
  184. )
  185. ).then(() => {
  186. const relativizeCode = (codeMatch, quot, depName) => {
  187. // if we have a canonical name for the module imported here,
  188. // we use it, so that require() is always called with the same
  189. // id for every module.
  190. // Example:
  191. // -- in a/b.js:
  192. // require('./c') => require('a/c');
  193. // -- in b/index.js:
  194. // require('../a/c') => require('a/c');
  195. const depId = resolvedDeps[depName];
  196. if (depId) {
  197. return quot + depId + quot;
  198. } else {
  199. return codeMatch;
  200. }
  201. };
  202. code = dependencyOffsets.reduceRight((codeBits, offset) => {
  203. const first = codeBits.shift();
  204. codeBits.unshift(
  205. first.slice(0, offset),
  206. first.slice(offset).replace(/(['"])([^'"']*)\1/, relativizeCode),
  207. );
  208. return codeBits;
  209. }, [code]);
  210. return code.join('');
  211. });
  212. });
  213. }
  214. wrapModule({
  215. resolutionResponse,
  216. module,
  217. name,
  218. map,
  219. code,
  220. meta = {},
  221. minify = false
  222. }) {
  223. if (module.isJSON()) {
  224. code = `module.exports = ${code}`;
  225. }
  226. const result = module.isPolyfill()
  227. ? Promise.resolve({code: definePolyfillCode(code)})
  228. : this.resolveRequires(
  229. resolutionResponse,
  230. module,
  231. code,
  232. meta.dependencyOffsets
  233. ).then(code => ({code: defineModuleCode(name, code), map}));
  234. return minify
  235. ? result.then(({code, map}) => this._minifyCode(module.path, code, map))
  236. : result;
  237. }
  238. getDebugInfo() {
  239. return this._depGraph.getDebugInfo();
  240. }
  241. }
  242. function defineModuleCode(moduleName, code) {
  243. return [
  244. `__d(`,
  245. `${JSON.stringify(moduleName)}, `,
  246. `function(global, require, module, exports) {`,
  247. `${code}`,
  248. '\n});',
  249. ].join('');
  250. }
  251. function definePolyfillCode(code,) {
  252. return [
  253. `(function(global) {`,
  254. code,
  255. `\n})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);`,
  256. ].join('');
  257. }
  258. module.exports = Resolver;