Refactor DependencyResolver into request/response

Reviewed By: @martinbigio

Differential Revision: D2425842
This commit is contained in:
Amjad Masad 2015-09-11 14:36:12 -07:00 committed by facebook-github-bot-2
parent 87d4d3c55c
commit 86a099d00a
13 changed files with 946 additions and 673 deletions

View File

@ -125,7 +125,7 @@ describe('Bundler', function() {
});
});
wrapModule.mockImpl(function(module, code) {
wrapModule.mockImpl(function(response, module, code) {
return Promise.resolve('lol ' + code + ' lol');
});

View File

@ -137,7 +137,7 @@ class Bundler {
const findEventId = Activity.startEvent('find dependencies');
let transformEventId;
return this.getDependencies(main, isDev, platform).then((result) => {
return this.getDependencies(main, isDev, platform).then((response) => {
Activity.endEvent(findEventId);
transformEventId = Activity.startEvent('transform');
@ -147,14 +147,19 @@ class Bundler {
complete: '=',
incomplete: ' ',
width: 40,
total: result.dependencies.length,
total: response.dependencies.length,
});
}
bundle.setMainModuleId(result.mainModuleId);
bundle.setMainModuleId(response.mainModuleId);
return Promise.all(
result.dependencies.map(
module => this._transformModule(bundle, module, platform).then(transformed => {
response.dependencies.map(
module => this._transformModule(
bundle,
response,
module,
platform
).then(transformed => {
if (bar) {
bar.tick();
}
@ -182,7 +187,7 @@ class Bundler {
return this._resolver.getDependencies(main, { dev: isDev, platform });
}
_transformModule(bundle, module, platform = null) {
_transformModule(bundle, response, module, platform = null) {
let transform;
if (module.isAsset_DEPRECATED()) {
@ -199,7 +204,11 @@ class Bundler {
const resolver = this._resolver;
return transform.then(
transformed => resolver.wrapModule(module, transformed.code).then(
transformed => resolver.wrapModule(
response,
module,
transformed.code
).then(
code => new ModuleTransport({
code: code,
map: transformed.map,

View File

@ -9,25 +9,8 @@
'use strict';
jest
.dontMock('absolute-path')
.dontMock('crypto')
.dontMock('underscore')
.dontMock('path')
.dontMock('../index')
.dontMock('../../lib/getAssetDataFromName')
.dontMock('../../DependencyResolver/crawlers')
.dontMock('../../DependencyResolver/crawlers/node')
.dontMock('../../DependencyResolver/DependencyGraph/docblock')
.dontMock('../../DependencyResolver/fastfs')
.dontMock('../../DependencyResolver/replacePatterns')
.dontMock('../../DependencyResolver')
.dontMock('../../DependencyResolver/DependencyGraph')
.dontMock('../../DependencyResolver/AssetModule_DEPRECATED')
.dontMock('../../DependencyResolver/AssetModule')
.dontMock('../../DependencyResolver/Module')
.dontMock('../../DependencyResolver/Package')
.dontMock('../../DependencyResolver/Polyfill')
.dontMock('../../DependencyResolver/ModuleCache');
.autoMockOff()
.mock('../../Cache');
const Promise = require('promise');
const path = require('path');

View File

@ -0,0 +1,100 @@
/**
* 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';
const Activity = require('../../Activity');
const AssetModule_DEPRECATED = require('../AssetModule_DEPRECATED');
const Fastfs = require('../fastfs');
const debug = require('debug')('ReactPackager:DependencyGraph');
const path = require('path');
class DeprecatedAssetMap {
constructor({ fsCrawl, roots, assetExts, fileWatcher, ignoreFilePath, helpers }) {
if (roots == null || roots.length === 0) {
this._disabled = true;
return;
}
this._helpers = helpers;
this._map = Object.create(null);
this._assetExts = assetExts;
this._fastfs = new Fastfs(
'Assets',
roots,
fileWatcher,
{ ignore: ignoreFilePath, crawling: fsCrawl }
);
this._fastfs.on('change', this._processFileChange.bind(this));
}
build() {
if (this._disabled) {
return Promise.resolve();
}
return this._fastfs.build().then(
() => {
const processAsset_DEPRECATEDActivity = Activity.startEvent(
'Building (deprecated) Asset Map',
);
this._fastfs.findFilesByExts(this._assetExts).forEach(
file => this._processAsset(file)
);
Activity.endEvent(processAsset_DEPRECATEDActivity);
}
);
}
resolve(fromModule, toModuleName) {
if (this._disabled) {
return null;
}
const assetMatch = toModuleName.match(/^image!(.+)/);
if (assetMatch && assetMatch[1]) {
if (!this._map[assetMatch[1]]) {
debug('WARINING: Cannot find asset:', assetMatch[1]);
return null;
}
return this._map[assetMatch[1]];
}
}
_processAsset(file) {
let ext = this._helpers.extname(file);
if (this._assetExts.indexOf(ext) !== -1) {
let name = assetName(file, ext);
if (this._map[name] != null) {
debug('Conflcting assets', name);
}
this._map[name] = new AssetModule_DEPRECATED(file);
}
}
_processFileChange(type, filePath, root, fstat) {
const name = assetName(filePath);
if (type === 'change' || type === 'delete') {
delete this._map[name];
}
if (type === 'change' || type === 'add') {
this._processAsset(path.join(root, filePath));
}
}
}
function assetName(file, ext) {
return path.basename(file, '.' + ext).replace(/@[\d\.]+x/, '');
}
module.exports = DeprecatedAssetMap;

View File

@ -0,0 +1,119 @@
/**
* 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';
const path = require('path');
const getPontentialPlatformExt = require('../../lib/getPlatformExtension');
class HasteMap {
constructor({ fastfs, moduleCache, helpers }) {
this._fastfs = fastfs;
this._moduleCache = moduleCache;
this._helpers = helpers;
this._map = Object.create(null);
}
build() {
let promises = this._fastfs.findFilesByExt('js', {
ignore: (file) => this._helpers.isNodeModulesDir(file)
}).map(file => this._processHasteModule(file));
promises = promises.concat(
this._fastfs.findFilesByName('package.json', {
ignore: (file) => this._helpers.isNodeModulesDir(file)
}).map(file => this._processHastePackage(file))
);
return Promise.all(promises);
}
processFileChange(type, absPath) {
return Promise.resolve().then(() => {
/*eslint no-labels: 0 */
if (type === 'delete' || type === 'change') {
loop: for (let name in this._map) {
let modules = this._map[name];
for (var i = 0; i < modules.length; i++) {
if (modules[i].path === absPath) {
modules.splice(i, 1);
break loop;
}
}
}
if (type === 'delete') {
return;
}
}
if (this._helpers.extname(absPath) === 'js' ||
this._helpers.extname(absPath) === 'json') {
if (path.basename(absPath) === 'package.json') {
return this._processHastePackage(absPath);
} else {
return this._processHasteModule(absPath);
}
}
});
}
getModule(name, platform = null) {
if (this._map[name]) {
const modules = this._map[name];
if (platform != null) {
for (let i = 0; i < modules.length; i++) {
if (getPontentialPlatformExt(modules[i].path) === platform) {
return modules[i];
}
}
}
return modules[0];
}
return null;
}
_processHasteModule(file) {
const module = this._moduleCache.getModule(file);
return module.isHaste().then(
isHaste => isHaste && module.getName()
.then(name => this._updateHasteMap(name, module))
);
}
_processHastePackage(file) {
file = path.resolve(file);
const p = this._moduleCache.getPackage(file, this._fastfs);
return p.isHaste()
.then(isHaste => isHaste && p.getName()
.then(name => this._updateHasteMap(name, p)))
.catch(e => {
if (e instanceof SyntaxError) {
// Malformed package.json.
return;
}
throw e;
});
}
_updateHasteMap(name, mod) {
if (this._map[name] == null) {
this._map[name] = [];
}
if (mod.type === 'Module') {
// Modules takes precendence over packages.
this._map[name].unshift(mod);
} else {
this._map[name].push(mod);
}
}
}
module.exports = HasteMap;

View File

@ -0,0 +1,49 @@
/**
* 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';
const path = require('path');
class Helpers {
constructor({ providesModuleNodeModules, assetExts }) {
this._providesModuleNodeModules = providesModuleNodeModules;
this._assetExts = assetExts;
}
isNodeModulesDir(file) {
let parts = path.normalize(file).split(path.sep);
const indexOfNodeModules = parts.lastIndexOf('node_modules');
if (indexOfNodeModules === -1) {
return false;
}
parts = parts.slice(indexOfNodeModules + 1);
const dirs = this._providesModuleNodeModules;
for (let i = 0; i < dirs.length; i++) {
if (parts.indexOf(dirs[i]) > -1) {
return false;
}
}
return true;
}
isAssetFile(file) {
return this._assetExts.indexOf(this.extname(file)) !== -1;
}
extname(name) {
return path.extname(name).replace(/^\./, '');
}
}
module.exports = Helpers;

View File

@ -0,0 +1,347 @@
/**
* 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';
const debug = require('debug')('ReactPackager:DependencyGraph');
const util = require('util');
const path = require('path');
const isAbsolutePath = require('absolute-path');
const getAssetDataFromName = require('../../lib/getAssetDataFromName');
class ResolutionRequest {
constructor({
platform,
entryPath,
hasteMap,
deprecatedAssetMap,
helpers,
moduleCache,
fastfs,
}) {
this._platform = platform;
this._entryPath = entryPath;
this._hasteMap = hasteMap;
this._deprecatedAssetMap = deprecatedAssetMap;
this._helpers = helpers;
this._moduleCache = moduleCache;
this._fastfs = fastfs;
this._resetResolutionCache();
}
_tryResolve(action, secondaryAction) {
return action().catch((error) => {
if (error.type !== 'UnableToResolveError') {
throw error;
}
return secondaryAction();
});
}
resolveDependency(fromModule, toModuleName) {
const resHash = resolutionHash(fromModule.path, toModuleName);
if (this._immediateResolutionCache[resHash]) {
return Promise.resolve(this._immediateResolutionCache[resHash]);
}
const asset_DEPRECATED = this._deprecatedAssetMap.resolve(
fromModule,
toModuleName
);
if (asset_DEPRECATED) {
return Promise.resolve(asset_DEPRECATED);
}
const cacheResult = (result) => {
this._immediateResolutionCache[resHash] = result;
return result;
};
const forgive = (error) => {
if (error.type !== 'UnableToResolveError') {
throw error;
}
console.warn(
'Unable to resolve module %s from %s',
toModuleName,
fromModule.path
);
return null;
};
if (!this._helpers.isNodeModulesDir(fromModule.path)
&& toModuleName[0] !== '.' &&
toModuleName[0] !== '/') {
return this._tryResolve(
() => this._resolveHasteDependency(fromModule, toModuleName),
() => this._resolveNodeDependency(fromModule, toModuleName)
).then(
cacheResult,
forgive,
);
}
return this._resolveNodeDependency(fromModule, toModuleName)
.then(
cacheResult,
forgive
);
}
getOrderedDependencies(response) {
return Promise.resolve().then(() => {
const entry = this._moduleCache.getModule(this._entryPath);
const visited = Object.create(null);
visited[entry.hash()] = true;
const collect = (mod) => {
response.pushDependency(mod);
return mod.getDependencies().then(
depNames => Promise.all(
depNames.map(name => this.resolveDependency(mod, name))
).then((dependencies) => [depNames, dependencies])
).then(([depNames, dependencies]) => {
let p = Promise.resolve();
const filteredPairs = [];
dependencies.forEach((modDep, i) => {
if (modDep == null) {
debug(
'WARNING: Cannot find required module `%s` from module `%s`',
depNames[i],
mod.path
);
return false;
}
return filteredPairs.push([depNames[i], modDep]);
});
response.setResolvedDependencyPairs(mod, filteredPairs);
filteredPairs.forEach(([depName, modDep]) => {
p = p.then(() => {
if (!visited[modDep.hash()]) {
visited[modDep.hash()] = true;
return collect(modDep);
}
return null;
});
});
return p;
});
};
return collect(entry);
});
}
getAsyncDependencies(response) {
return Promise.resolve().then(() => {
const mod = this._moduleCache.getModule(this._entryPath);
return mod.getAsyncDependencies().then(bundles =>
Promise
.all(bundles.map(bundle =>
Promise.all(bundle.map(
dep => this.resolveDependency(mod, dep)
))
))
.then(bs => bs.map(bundle => bundle.map(dep => dep.path)))
);
}).then(asyncDependencies => asyncDependencies.forEach(
(dependency) => response.pushAsyncDependency(dependency)
));
}
_resolveHasteDependency(fromModule, toModuleName) {
toModuleName = normalizePath(toModuleName);
let p = fromModule.getPackage();
if (p) {
p = p.redirectRequire(toModuleName);
} else {
p = Promise.resolve(toModuleName);
}
return p.then((realModuleName) => {
let dep = this._hasteMap.getModule(realModuleName, this._platform);
if (dep && dep.type === 'Module') {
return dep;
}
let packageName = realModuleName;
while (packageName && packageName !== '.') {
dep = this._hasteMap.getModule(packageName, this._platform);
if (dep && dep.type === 'Package') {
break;
}
packageName = path.dirname(packageName);
}
if (dep && dep.type === 'Package') {
const potentialModulePath = path.join(
dep.root,
path.relative(packageName, realModuleName)
);
return this._tryResolve(
() => this._loadAsFile(potentialModulePath),
() => this._loadAsDir(potentialModulePath),
);
}
throw new UnableToResolveError('Unable to resolve dependency');
});
}
_redirectRequire(fromModule, modulePath) {
return Promise.resolve(fromModule.getPackage()).then(p => {
if (p) {
return p.redirectRequire(modulePath);
}
return modulePath;
});
}
_resolveNodeDependency(fromModule, toModuleName) {
if (toModuleName[0] === '.' || toModuleName[1] === '/') {
const potentialModulePath = isAbsolutePath(toModuleName) ?
toModuleName :
path.join(path.dirname(fromModule.path), toModuleName);
return this._redirectRequire(fromModule, potentialModulePath).then(
realModuleName => this._tryResolve(
() => this._loadAsFile(realModuleName),
() => this._loadAsDir(realModuleName)
)
);
} else {
return this._redirectRequire(fromModule, toModuleName).then(
realModuleName => {
const searchQueue = [];
for (let currDir = path.dirname(fromModule.path);
currDir !== '/';
currDir = path.dirname(currDir)) {
searchQueue.push(
path.join(currDir, 'node_modules', realModuleName)
);
}
let p = Promise.reject(new UnableToResolveError('Node module not found'));
searchQueue.forEach(potentialModulePath => {
p = this._tryResolve(
() => this._tryResolve(
() => p,
() => this._loadAsFile(potentialModulePath),
),
() => this._loadAsDir(potentialModulePath)
);
});
return p;
});
}
}
_loadAsFile(potentialModulePath) {
return Promise.resolve().then(() => {
if (this._helpers.isAssetFile(potentialModulePath)) {
const {name, type} = getAssetDataFromName(potentialModulePath);
let pattern = '^' + name + '(@[\\d\\.]+x)?';
if (this._platform != null) {
pattern += '(\\.' + this._platform + ')?';
}
pattern += '\\.' + type;
// We arbitrarly grab the first one, because scale selection
// will happen somewhere
const [assetFile] = this._fastfs.matches(
path.dirname(potentialModulePath),
new RegExp(pattern)
);
if (assetFile) {
return this._moduleCache.getAssetModule(assetFile);
}
}
let file;
if (this._fastfs.fileExists(potentialModulePath)) {
file = potentialModulePath;
} else if (this._platform != null &&
this._fastfs.fileExists(potentialModulePath + '.' + this._platform + '.js')) {
file = potentialModulePath + '.' + this._platform + '.js';
} else if (this._fastfs.fileExists(potentialModulePath + '.js')) {
file = potentialModulePath + '.js';
} else if (this._fastfs.fileExists(potentialModulePath + '.json')) {
file = potentialModulePath + '.json';
} else {
throw new UnableToResolveError(`File ${potentialModulePath} doesnt exist`);
}
return this._moduleCache.getModule(file);
});
}
_loadAsDir(potentialDirPath) {
return Promise.resolve().then(() => {
if (!this._fastfs.dirExists(potentialDirPath)) {
throw new UnableToResolveError(`Invalid directory ${potentialDirPath}`);
}
const packageJsonPath = path.join(potentialDirPath, 'package.json');
if (this._fastfs.fileExists(packageJsonPath)) {
return this._moduleCache.getPackage(packageJsonPath)
.getMain().then(
(main) => this._tryResolve(
() => this._loadAsFile(main),
() => this._loadAsDir(main)
)
);
}
return this._loadAsFile(path.join(potentialDirPath, 'index'));
});
}
_resetResolutionCache() {
this._immediateResolutionCache = Object.create(null);
}
}
function resolutionHash(modulePath, depName) {
return `${path.resolve(modulePath)}:${depName}`;
}
function UnableToResolveError() {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
var msg = util.format.apply(util, arguments);
this.message = msg;
this.type = this.name = 'UnableToResolveError';
}
util.inherits(UnableToResolveError, Error);
function normalizePath(modulePath) {
if (path.sep === '/') {
modulePath = path.normalize(modulePath);
} else if (path.posix) {
modulePath = path.posix.normalize(modulePath);
}
return modulePath.replace(/\/$/, '');
}
module.exports = ResolutionRequest;

View File

@ -0,0 +1,73 @@
/**
* 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';
class ResolutionResponse {
constructor() {
this.dependencies = [];
this.asyncDependencies = [];
this.mainModuleId = null;
this._mappings = Object.create(null);
this._finalized = false;
}
_assertNotFinalized() {
if (this._finalized) {
throw new Error('Attempted to mutate finalized response.');
}
}
_assertFinalized() {
if (!this._finalized) {
throw new Error('Attempted to access unfinalized response.');
}
}
finalize() {
return this._mainModule.getName().then(id => {
this.mainModuleId = id;
this._finalized = true;
return this;
});
}
pushDependency(module) {
this._assertNotFinalized();
if (this.dependencies.length === 0) {
this._mainModule = module;
}
this.dependencies.push(module);
}
prependDependency(module) {
this._assertNotFinalized();
this.dependencies.unshift(module);
}
pushAsyncDependency(dependency){
this._assertNotFinalized();
this.asyncDependencies.push(dependency);
}
setResolvedDependencyPairs(module, pairs) {
this._assertNotFinalized();
const hash = module.hash();
if (this._mappings[hash] == null) {
this._mappings[hash] = pairs;
}
}
getResolvedDependencyPairs(module) {
this._assertFinalized();
return this._mappings[module.hash()];
}
}
module.exports = ResolutionResponse;

View File

@ -8,26 +8,13 @@
*/
'use strict';
jest
.dontMock('../index')
.dontMock('crypto')
.dontMock('absolute-path')
.dontMock('../docblock')
.dontMock('../../crawlers')
.dontMock('../../crawlers/node')
.dontMock('../../replacePatterns')
.dontMock('../../../lib/getPlatformExtension')
.dontMock('../../../lib/getAssetDataFromName')
.dontMock('../../fastfs')
.dontMock('../../AssetModule_DEPRECATED')
.dontMock('../../AssetModule')
.dontMock('../../Module')
.dontMock('../../Package')
.dontMock('../../ModuleCache');
jest.autoMockOff();
const Promise = require('promise');
jest.mock('fs');
jest
.mock('fs')
.mock('../../../Cache');
describe('DependencyGraph', function() {
var cache;
@ -36,12 +23,13 @@ describe('DependencyGraph', function() {
var fileWatcher;
var fs;
function getOrderedDependenciesAsJSON(dgraph, entry) {
return dgraph.getOrderedDependencies(entry).then(
deps => Promise.all(deps.map(dep => Promise.all([
function getOrderedDependenciesAsJSON(dgraph, entry, platform) {
return dgraph.getDependencies(entry, platform)
.then(response => response.finalize())
.then(({ dependencies }) => Promise.all(dependencies.map(dep => Promise.all([
dep.getName(),
dep.getDependencies(),
]).then(([name, dependencies]) => ({
]).then(([name, moduleDependencies]) => ({
path: dep.path,
isJSON: dep.isJSON(),
isAsset: dep.isAsset(),
@ -49,7 +37,7 @@ describe('DependencyGraph', function() {
isPolyfill: dep.isPolyfill(),
resolution: dep.resolution,
id: name,
dependencies
dependencies: moduleDependencies,
})))
));
}
@ -66,10 +54,10 @@ describe('DependencyGraph', function() {
isWatchman: () => Promise.resolve(false)
};
cache = new Cache({});
cache = new Cache();
});
describe('getOrderedDependencies', function() {
describe('get sync dependencies', function() {
pit('should get dependencies', function() {
var root = '/root';
fs.__setMockFilesystem({
@ -455,9 +443,7 @@ describe('DependencyGraph', function() {
cache: cache,
});
dgraph.setup({ platform: 'ios' });
return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) {
return getOrderedDependenciesAsJSON(dgraph, '/root/index.js', 'ios').then(function(deps) {
expect(deps)
.toEqual([
{
@ -3699,4 +3685,40 @@ describe('DependencyGraph', function() {
});
});
});
describe('getAsyncDependencies', () => {
pit('should get dependencies', function() {
var root = '/root';
fs.__setMockFilesystem({
'root': {
'index.js': [
'/**',
' * @providesModule index',
' */',
'System.import("a")'
].join('\n'),
'a.js': [
'/**',
' * @providesModule a',
' */',
].join('\n'),
}
});
var dgraph = new DependencyGraph({
roots: [root],
fileWatcher: fileWatcher,
assetExts: ['png', 'jpg'],
cache: cache,
});
return dgraph.getDependencies('/root/index.js')
.then(response => response.finalize())
.then(({ asyncDependencies }) => {
expect(asyncDependencies).toEqual([
['/root/a.js']
]);
});
});
});
});

View File

@ -9,18 +9,20 @@
'use strict';
const Activity = require('../../Activity');
const AssetModule_DEPRECATED = require('../AssetModule_DEPRECATED');
const Fastfs = require('../fastfs');
const ModuleCache = require('../ModuleCache');
const Promise = require('promise');
const crawl = require('../crawlers');
const debug = require('debug')('DependencyGraph');
const declareOpts = require('../../lib/declareOpts');
const getAssetDataFromName = require('../../lib/getAssetDataFromName');
const getPontentialPlatformExt = require('../../lib/getPlatformExtension');
const isAbsolutePath = require('absolute-path');
const path = require('path');
const util = require('util');
const Helpers = require('./Helpers');
const ResolutionRequest = require('./ResolutionRequest');
const ResolutionResponse = require('./ResolutionResponse');
const HasteMap = require('./HasteMap');
const DeprecatedAssetMap = require('./DeprecatedAssetMap');
const validateOpts = declareOpts({
roots: {
@ -69,9 +71,8 @@ const validateOpts = declareOpts({
class DependencyGraph {
constructor(options) {
this._opts = validateOpts(options);
this._hasteMap = Object.create(null);
this._resetResolutionCache();
this._cache = this._opts.cache;
this._helpers = new Helpers(this._opts);
this.load();
}
@ -104,13 +105,29 @@ class DependencyGraph {
this._moduleCache = new ModuleCache(this._fastfs, this._cache);
this._hasteMap = new HasteMap({
fastfs: this._fastfs,
moduleCache: this._moduleCache,
assetExts: this._opts.exts,
helpers: this._helpers,
});
this._deprecatedAssetMap = new DeprecatedAssetMap({
fsCrawl: this._crawling,
roots: this._opts.assetRoots_DEPRECATED,
helpers: this._helpers,
fileWatcher: this._opts.fileWatcher,
ignoreFilePath: this._opts.ignoreFilePath,
assetExts: this._opts.assetExts,
});
this._loading = Promise.all([
this._fastfs.build()
.then(() => {
const hasteActivity = Activity.startEvent('Building Haste Map');
return this._buildHasteMap().then(() => Activity.endEvent(hasteActivity));
return this._hasteMap.build().then(() => Activity.endEvent(hasteActivity));
}),
this._buildAssetMap_DEPRECATED(),
this._deprecatedAssetMap.build(),
]).then(() =>
Activity.endEvent(depGraphActivity)
);
@ -118,536 +135,73 @@ class DependencyGraph {
return this._loading;
}
setup({ platform }) {
if (platform && this._opts.platforms.indexOf(platform) === -1) {
getDependencies(entryPath, platform) {
return this.load().then(() => {
platform = this._getRequestPlatform(entryPath, platform);
const absPath = this._getAbsolutePath(entryPath);
const req = new ResolutionRequest({
platform,
entryPath: absPath,
deprecatedAssetMap: this._deprecatedAssetMap,
hasteMap: this._hasteMap,
helpers: this._helpers,
moduleCache: this._moduleCache,
fastfs: this._fastfs,
});
const response = new ResolutionResponse();
return Promise.all([
req.getOrderedDependencies(response),
req.getAsyncDependencies(response),
]).then(() => response);
});
}
_getRequestPlatform(entryPath, platform) {
if (platform == null) {
platform = getPontentialPlatformExt(entryPath);
if (platform == null || this._opts.platforms.indexOf(platform) === -1) {
platform = null;
}
} else if (this._opts.platforms.indexOf(platform) === -1) {
throw new Error('Unrecognized platform: ' + platform);
}
// TODO(amasad): This is a potential race condition. Mutliple requests could
// interfere with each other. This needs a refactor to fix -- which will
// follow this diff.
if (this._platformExt !== platform) {
this._resetResolutionCache();
}
this._platformExt = platform;
}
resolveDependency(fromModule, toModuleName) {
const resHash = resolutionHash(fromModule.path, toModuleName);
if (this._immediateResolutionCache[resHash]) {
return Promise.resolve(this._immediateResolutionCache[resHash]);
}
const asset_DEPRECATED = this._resolveAsset_DEPRECATED(
fromModule,
toModuleName
);
if (asset_DEPRECATED) {
return Promise.resolve(asset_DEPRECATED);
}
const cacheResult = (result) => {
this._immediateResolutionCache[resHash] = result;
return result;
};
const forgive = () => {
console.warn(
'Unable to resolve module %s from %s',
toModuleName,
fromModule.path
);
return null;
};
if (!this._isNodeModulesDir(fromModule.path)
&& toModuleName[0] !== '.' &&
toModuleName[0] !== '/') {
return this._resolveHasteDependency(fromModule, toModuleName).catch(
() => this._resolveNodeDependency(fromModule, toModuleName)
).then(
cacheResult,
forgive,
);
}
return this._resolveNodeDependency(fromModule, toModuleName)
.then(
cacheResult,
forgive
);
}
getOrderedDependencies(entryPath) {
return this.load().then(() => {
const entry = this._getModuleForEntryPath(entryPath);
const deps = [];
const visited = Object.create(null);
visited[entry.hash()] = true;
const collect = (mod) => {
deps.push(mod);
return mod.getDependencies().then(
depNames => Promise.all(
depNames.map(name => this.resolveDependency(mod, name))
).then((dependencies) => [depNames, dependencies])
).then(([depNames, dependencies]) => {
let p = Promise.resolve();
dependencies.forEach((modDep, i) => {
if (modDep == null) {
debug(
'WARNING: Cannot find required module `%s` from module `%s`',
depNames[i],
mod.path
);
return;
}
p = p.then(() => {
if (!visited[modDep.hash()]) {
visited[modDep.hash()] = true;
return collect(modDep);
}
return null;
});
});
return p;
});
};
return collect(entry)
.then(() => deps);
});
}
getAsyncDependencies(entryPath) {
return this.load().then(() => {
const mod = this._getModuleForEntryPath(entryPath);
return mod.getAsyncDependencies().then(bundles =>
Promise
.all(bundles.map(bundle =>
Promise.all(bundle.map(
dep => this.resolveDependency(mod, dep)
))
))
.then(bs => bs.map(bundle => bundle.map(dep => dep.path)))
);
});
return platform;
}
_getAbsolutePath(filePath) {
if (isAbsolutePath(filePath)) {
return filePath;
return path.resolve(filePath);
}
for (let i = 0; i < this._opts.roots.length; i++) {
const root = this._opts.roots[i];
const absPath = path.join(root, filePath);
if (this._fastfs.fileExists(absPath)) {
return absPath;
const potentialAbsPath = path.join(root, filePath);
if (this._fastfs.fileExists(potentialAbsPath)) {
return path.resolve(potentialAbsPath);
}
}
return null;
}
_getModuleForEntryPath(entryPath) {
const absPath = this._getAbsolutePath(entryPath);
if (absPath == null) {
throw new NotFoundError(
'Could not find source file at %s',
entryPath
);
}
const absolutePath = path.resolve(absPath);
if (absolutePath == null) {
throw new NotFoundError(
'Cannot find entry file %s in any of the roots: %j',
entryPath,
this._opts.roots
);
}
// `platformExt` could be set in the `setup` method.
if (!this._platformExt) {
const platformExt = getPontentialPlatformExt(entryPath);
if (platformExt && this._opts.platforms.indexOf(platformExt) > -1) {
this._platformExt = platformExt;
} else {
this._platformExt = null;
}
}
return this._moduleCache.getModule(absolutePath);
}
_resolveHasteDependency(fromModule, toModuleName) {
toModuleName = normalizePath(toModuleName);
let p = fromModule.getPackage();
if (p) {
p = p.redirectRequire(toModuleName);
} else {
p = Promise.resolve(toModuleName);
}
return p.then((realModuleName) => {
let dep = this._getHasteModule(realModuleName);
if (dep && dep.type === 'Module') {
return dep;
}
let packageName = realModuleName;
while (packageName && packageName !== '.') {
dep = this._getHasteModule(packageName);
if (dep && dep.type === 'Package') {
break;
}
packageName = path.dirname(packageName);
}
if (dep && dep.type === 'Package') {
const potentialModulePath = path.join(
dep.root,
path.relative(packageName, realModuleName)
);
return this._loadAsFile(potentialModulePath)
.catch(() => this._loadAsDir(potentialModulePath));
}
throw new Error('Unable to resolve dependency');
});
}
_redirectRequire(fromModule, modulePath) {
return Promise.resolve(fromModule.getPackage()).then(p => {
if (p) {
return p.redirectRequire(modulePath);
}
return modulePath;
});
}
_resolveNodeDependency(fromModule, toModuleName) {
if (toModuleName[0] === '.' || toModuleName[1] === '/') {
const potentialModulePath = isAbsolutePath(toModuleName) ?
toModuleName :
path.join(path.dirname(fromModule.path), toModuleName);
return this._redirectRequire(fromModule, potentialModulePath).then(
realModuleName => this._loadAsFile(realModuleName)
.catch(() => this._loadAsDir(realModuleName))
);
} else {
return this._redirectRequire(fromModule, toModuleName).then(
realModuleName => {
const searchQueue = [];
for (let currDir = path.dirname(fromModule.path);
currDir !== '/';
currDir = path.dirname(currDir)) {
searchQueue.push(
path.join(currDir, 'node_modules', realModuleName)
);
}
let p = Promise.reject(new Error('Node module not found'));
searchQueue.forEach(potentialModulePath => {
p = p.catch(
() => this._loadAsFile(potentialModulePath)
).catch(
() => this._loadAsDir(potentialModulePath)
);
});
return p;
});
}
}
_resolveAsset_DEPRECATED(fromModule, toModuleName) {
if (this._assetMap_DEPRECATED != null) {
const assetMatch = toModuleName.match(/^image!(.+)/);
// Process DEPRECATED global asset requires.
if (assetMatch && assetMatch[1]) {
if (!this._assetMap_DEPRECATED[assetMatch[1]]) {
debug('WARINING: Cannot find asset:', assetMatch[1]);
return null;
}
return this._assetMap_DEPRECATED[assetMatch[1]];
}
}
return null;
}
_isAssetFile(file) {
return this._opts.assetExts.indexOf(extname(file)) !== -1;
}
_loadAsFile(potentialModulePath) {
return Promise.resolve().then(() => {
if (this._isAssetFile(potentialModulePath)) {
const {name, type} = getAssetDataFromName(potentialModulePath);
let pattern = '^' + name + '(@[\\d\\.]+x)?';
if (this._platformExt != null) {
pattern += '(\\.' + this._platformExt + ')?';
}
pattern += '\\.' + type;
// We arbitrarly grab the first one, because scale selection
// will happen somewhere
const [assetFile] = this._fastfs.matches(
path.dirname(potentialModulePath),
new RegExp(pattern)
);
if (assetFile) {
return this._moduleCache.getAssetModule(assetFile);
}
}
let file;
if (this._fastfs.fileExists(potentialModulePath)) {
file = potentialModulePath;
} else if (this._platformExt != null &&
this._fastfs.fileExists(potentialModulePath + '.' + this._platformExt + '.js')) {
file = potentialModulePath + '.' + this._platformExt + '.js';
} else if (this._fastfs.fileExists(potentialModulePath + '.js')) {
file = potentialModulePath + '.js';
} else if (this._fastfs.fileExists(potentialModulePath + '.json')) {
file = potentialModulePath + '.json';
} else {
throw new Error(`File ${potentialModulePath} doesnt exist`);
}
return this._moduleCache.getModule(file);
});
}
_loadAsDir(potentialDirPath) {
return Promise.resolve().then(() => {
if (!this._fastfs.dirExists(potentialDirPath)) {
throw new Error(`Invalid directory ${potentialDirPath}`);
}
const packageJsonPath = path.join(potentialDirPath, 'package.json');
if (this._fastfs.fileExists(packageJsonPath)) {
return this._moduleCache.getPackage(packageJsonPath)
.getMain().then(
(main) => this._loadAsFile(main).catch(
() => this._loadAsDir(main)
)
);
}
return this._loadAsFile(path.join(potentialDirPath, 'index'));
});
}
_buildHasteMap() {
let promises = this._fastfs.findFilesByExt('js', {
ignore: (file) => this._isNodeModulesDir(file)
}).map(file => this._processHasteModule(file));
promises = promises.concat(
this._fastfs.findFilesByName('package.json', {
ignore: (file) => this._isNodeModulesDir(file)
}).map(file => this._processHastePackage(file))
throw new NotFoundError(
'Cannot find entry file %s in any of the roots: %j',
filePath,
this._opts.roots
);
return Promise.all(promises);
}
_processHasteModule(file) {
const module = this._moduleCache.getModule(file);
return module.isHaste().then(
isHaste => isHaste && module.getName()
.then(name => this._updateHasteMap(name, module))
);
}
_processHastePackage(file) {
file = path.resolve(file);
const p = this._moduleCache.getPackage(file, this._fastfs);
return p.isHaste()
.then(isHaste => isHaste && p.getName()
.then(name => this._updateHasteMap(name, p)))
.catch(e => {
if (e instanceof SyntaxError) {
// Malformed package.json.
return;
}
throw e;
});
}
_updateHasteMap(name, mod) {
if (this._hasteMap[name] == null) {
this._hasteMap[name] = [];
}
if (mod.type === 'Module') {
// Modules takes precendence over packages.
this._hasteMap[name].unshift(mod);
} else {
this._hasteMap[name].push(mod);
}
}
_getHasteModule(name) {
if (this._hasteMap[name]) {
const modules = this._hasteMap[name];
if (this._platformExt != null) {
for (let i = 0; i < modules.length; i++) {
if (getPontentialPlatformExt(modules[i].path) === this._platformExt) {
return modules[i];
}
}
}
return modules[0];
}
return null;
}
_isNodeModulesDir(file) {
let parts = path.normalize(file).split(path.sep);
const indexOfNodeModules = parts.lastIndexOf('node_modules');
if (indexOfNodeModules === -1) {
return false;
}
parts = parts.slice(indexOfNodeModules + 1);
const dirs = this._opts.providesModuleNodeModules;
for (let i = 0; i < dirs.length; i++) {
if (parts.indexOf(dirs[i]) > -1) {
return false;
}
}
return true;
}
_processAsset_DEPRECATED(file) {
let ext = extname(file);
if (this._opts.assetExts.indexOf(ext) !== -1) {
let name = assetName(file, ext);
if (this._assetMap_DEPRECATED[name] != null) {
debug('Conflcting assets', name);
}
this._assetMap_DEPRECATED[name] = new AssetModule_DEPRECATED(file);
}
}
_buildAssetMap_DEPRECATED() {
if (this._opts.assetRoots_DEPRECATED == null ||
this._opts.assetRoots_DEPRECATED.length === 0) {
return Promise.resolve();
}
this._assetMap_DEPRECATED = Object.create(null);
const fastfs = new Fastfs(
'Assets',
this._opts.assetRoots_DEPRECATED,
this._opts.fileWatcher,
{ ignore: this._opts.ignoreFilePath, crawling: this._crawling }
);
fastfs.on('change', this._processAssetChange_DEPRECATED.bind(this));
return fastfs.build().then(
() => {
const processAsset_DEPRECATEDActivity = Activity.startEvent(
'Building (deprecated) Asset Map',
);
const assets = fastfs.findFilesByExts(this._opts.assetExts).map(
file => this._processAsset_DEPRECATED(file)
);
Activity.endEvent(processAsset_DEPRECATEDActivity);
return assets;
}
);
}
_processAssetChange_DEPRECATED(type, filePath, root, fstat) {
const name = assetName(filePath);
if (type === 'change' || type === 'delete') {
delete this._assetMap_DEPRECATED[name];
}
if (type === 'change' || type === 'add') {
this._loading = this._loading.then(
() => this._processAsset_DEPRECATED(path.join(root, filePath))
);
}
}
_processFileChange(type, filePath, root, fstat) {
// It's really hard to invalidate the right module resolution cache
// so we just blow it up with every file change.
this._resetResolutionCache();
const absPath = path.join(root, filePath);
if ((fstat && fstat.isDirectory()) ||
if (fstat && fstat.isDirectory() ||
this._opts.ignoreFilePath(absPath) ||
this._isNodeModulesDir(absPath)) {
this._helpers.isNodeModulesDir(absPath)) {
return;
}
/*eslint no-labels: 0 */
if (type === 'delete' || type === 'change') {
loop: for (let name in this._hasteMap) {
let modules = this._hasteMap[name];
for (var i = 0; i < modules.length; i++) {
if (modules[i].path === absPath) {
modules.splice(i, 1);
break loop;
}
}
}
if (type === 'delete') {
return;
}
}
if (extname(absPath) === 'js' || extname(absPath) === 'json') {
this._loading = this._loading.then(() => {
if (path.basename(filePath) === 'package.json') {
return this._processHastePackage(absPath);
} else {
return this._processHasteModule(absPath);
}
});
}
this._loading = this._loading.then(
() => this._hasteMap.processFileChange(type, absPath)
);
}
_resetResolutionCache() {
this._immediateResolutionCache = Object.create(null);
}
}
function assetName(file, ext) {
return path.basename(file, '.' + ext).replace(/@[\d\.]+x/, '');
}
function extname(name) {
return path.extname(name).replace(/^\./, '');
}
function resolutionHash(modulePath, depName) {
return `${path.resolve(modulePath)}:${depName}`;
}
function NotFoundError() {
@ -658,17 +212,6 @@ function NotFoundError() {
this.type = this.name = 'NotFoundError';
this.status = 404;
}
function normalizePath(modulePath) {
if (path.sep === '/') {
modulePath = path.normalize(modulePath);
} else if (path.posix) {
modulePath = path.posix.normalize(modulePath);
}
return modulePath.replace(/\/$/, '');
}
util.inherits(NotFoundError, Error);
module.exports = DependencyGraph;

View File

@ -34,6 +34,22 @@ describe('HasteDependencyResolver', function() {
HasteDependencyResolver = require('../');
});
class ResolutionResponseMock {
constructor({dependencies, mainModuleId, asyncDependencies}) {
this.dependencies = dependencies;
this.mainModuleId = mainModuleId;
this.asyncDependencies = asyncDependencies;
}
prependDependency(dependency) {
this.dependencies.unshift(dependency);
}
finalize() {
return Promise.resolve(this);
}
}
function createModule(id, dependencies) {
var module = new Module();
module.getName.mockImpl(() => Promise.resolve(id));
@ -52,11 +68,12 @@ describe('HasteDependencyResolver', function() {
// Is there a better way? How can I mock the prototype instead?
var depGraph = depResolver._depGraph;
depGraph.getOrderedDependencies.mockImpl(function() {
return Promise.resolve(deps);
});
depGraph.load.mockImpl(function() {
return Promise.resolve();
depGraph.getDependencies.mockImpl(function() {
return Promise.resolve(new ResolutionResponseMock({
dependencies: deps,
mainModuleId: 'index',
asyncDependencies: [],
}));
});
return depResolver.getDependencies('/root/index.js', { dev: false })
@ -133,19 +150,19 @@ describe('HasteDependencyResolver', function() {
projectRoot: '/root',
});
// Is there a better way? How can I mock the prototype instead?
var depGraph = depResolver._depGraph;
depGraph.getOrderedDependencies.mockImpl(function() {
return Promise.resolve(deps);
});
depGraph.load.mockImpl(function() {
return Promise.resolve();
depGraph.getDependencies.mockImpl(function() {
return Promise.resolve(new ResolutionResponseMock({
dependencies: deps,
mainModuleId: 'index',
asyncDependencies: [],
}));
});
return depResolver.getDependencies('/root/index.js', { dev: true })
.then(function(result) {
expect(result.mainModuleId).toEqual('index');
expect(depGraph.getOrderedDependencies).toBeCalledWith('/root/index.js');
expect(depGraph.getDependencies).toBeCalledWith('/root/index.js', undefined);
expect(result.dependencies[0]).toBe(Polyfill.mock.instances[0]);
expect(result.dependencies[result.dependencies.length - 1])
.toBe(module);
@ -161,13 +178,13 @@ describe('HasteDependencyResolver', function() {
polyfillModuleNames: ['some module'],
});
// Is there a better way? How can I mock the prototype instead?
var depGraph = depResolver._depGraph;
depGraph.getOrderedDependencies.mockImpl(function() {
return Promise.resolve(deps);
});
depGraph.load.mockImpl(function() {
return Promise.resolve();
depGraph.getDependencies.mockImpl(function() {
return Promise.resolve(new ResolutionResponseMock({
dependencies: deps,
mainModuleId: 'index',
asyncDependencies: [],
}));
});
return depResolver.getDependencies('/root/index.js', { dev: false })
@ -343,17 +360,23 @@ describe('HasteDependencyResolver', function() {
].join('\n');
/*eslint-disable */
depGraph.resolveDependency.mockImpl(function(fromModule, toModuleName) {
if (toModuleName === 'x') {
return Promise.resolve(createModule('changed'));
} else if (toModuleName === 'y') {
return Promise.resolve(createModule('Y'));
}
const module = createModule('test module', ['x', 'y']);
return Promise.resolve(null);
const resolutionResponse = new ResolutionResponseMock({
dependencies: [module],
mainModuleId: 'test module',
asyncDependencies: [],
});
resolutionResponse.getResolvedDependencyPairs = (module) => {
return [
['x', createModule('changed')],
['y', createModule('Y')],
];
}
return depResolver.wrapModule(
resolutionResponse,
createModule('test module', ['x', 'y']),
code
).then(processedCode => {

View File

@ -13,6 +13,8 @@ const stat = Promise.denodeify(fs.stat);
const hasOwn = Object.prototype.hasOwnProperty;
const NOT_FOUND_IN_ROOTS = 'NotFoundInRootsError';
class Fastfs extends EventEmitter {
constructor(name, roots, fileWatcher, {ignore, crawling}) {
super();
@ -90,7 +92,11 @@ class Fastfs extends EventEmitter {
}
readFile(filePath) {
return this._getFile(filePath).read();
const file = this._getFile(filePath);
if (!file) {
throw new Error(`Unable to find file with path: ${file}`);
}
return file.read();
}
closest(filePath, name) {
@ -105,12 +111,30 @@ class Fastfs extends EventEmitter {
}
fileExists(filePath) {
const file = this._getFile(filePath);
let file;
try {
file = this._getFile(filePath);
} catch (e) {
if (e.type === NOT_FOUND_IN_ROOTS) {
return false;
}
throw e;
}
return file && !file.isDir;
}
dirExists(filePath) {
const file = this._getFile(filePath);
let file;
try {
file = this._getFile(filePath);
} catch (e) {
if (e.type === NOT_FOUND_IN_ROOTS) {
return false;
}
throw e;
}
return file && file.isDir;
}
@ -138,7 +162,9 @@ class Fastfs extends EventEmitter {
_getAndAssertRoot(filePath) {
const root = this._getRoot(filePath);
if (!root) {
throw new Error(`File ${filePath} not found in any of the roots`);
const error = new Error(`File ${filePath} not found in any of the roots`);
error.type = NOT_FOUND_IN_ROOTS;
throw error;
}
return root;
}

View File

@ -82,36 +82,18 @@ var getDependenciesValidateOpts = declareOpts({
HasteDependencyResolver.prototype.getDependencies = function(main, options) {
var opts = getDependenciesValidateOpts(options);
var depGraph = this._depGraph;
var self = this;
return this._depGraph.getDependencies(main, opts.platform).then(
resolutionResponse => {
this._getPolyfillDependencies(opts.dev).reverse().forEach(
polyfill => resolutionResponse.prependDependency(polyfill)
);
depGraph.setup({ platform: opts.platform });
return Promise.all([
depGraph.getOrderedDependencies(main),
depGraph.getAsyncDependencies(main),
]).then(
([dependencies, asyncDependencies]) => dependencies[0].getName().then(
mainModuleId => {
self._prependPolyfillDependencies(
dependencies,
opts.dev,
);
return {
mainModuleId,
dependencies,
asyncDependencies,
};
}
)
return resolutionResponse.finalize();
}
);
};
HasteDependencyResolver.prototype._prependPolyfillDependencies = function(
dependencies,
isDev
) {
HasteDependencyResolver.prototype._getPolyfillDependencies = function(isDev) {
var polyfillModuleNames = [
isDev
? path.join(__dirname, 'polyfills/prelude_dev.js')
@ -124,7 +106,7 @@ HasteDependencyResolver.prototype._prependPolyfillDependencies = function(
path.join(__dirname, 'polyfills/Array.prototype.es6.js'),
].concat(this._polyfillModuleNames);
var polyfillModules = polyfillModuleNames.map(
return polyfillModuleNames.map(
(polyfillModuleName, idx) => new Polyfill({
path: polyfillModuleName,
id: polyfillModuleName,
@ -132,50 +114,47 @@ HasteDependencyResolver.prototype._prependPolyfillDependencies = function(
isPolyfill: true,
})
);
dependencies.unshift.apply(dependencies, polyfillModules);
};
HasteDependencyResolver.prototype.wrapModule = function(module, code) {
if (module.isPolyfill()) {
return Promise.resolve(code);
}
HasteDependencyResolver.prototype.wrapModule = function(resolutionResponse, module, code) {
return Promise.resolve().then(() => {
if (module.isPolyfill()) {
return Promise.resolve(code);
}
const resolvedDeps = Object.create(null);
const resolvedDepsArr = [];
const resolvedDeps = Object.create(null);
const resolvedDepsArr = [];
return module.getDependencies().then(
dependencies => Promise.all(dependencies.map(
depName => this._depGraph.resolveDependency(module, depName)
.then(depModule => {
if (depModule) {
return depModule.getName().then(name => {
resolvedDeps[depName] = name;
resolvedDepsArr.push(name);
});
}
})
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;
}
};
).then(() => {
const relativizeCode = (codeMatch, pre, quot, depName, post) => {
const depId = resolvedDeps[depName];
if (depId) {
return pre + quot + depId + post;
} else {
return codeMatch;
}
};
return module.getName().then(
name => defineModuleCode({
code: code
.replace(replacePatterns.IMPORT_RE, relativizeCode)
.replace(replacePatterns.REQUIRE_RE, relativizeCode),
deps: JSON.stringify(resolvedDepsArr),
moduleName: name,
})
);
return module.getName().then(
name => defineModuleCode({
code: code.replace(replacePatterns.IMPORT_RE, relativizeCode)
.replace(replacePatterns.REQUIRE_RE, relativizeCode),
deps: JSON.stringify(resolvedDepsArr),
moduleName: name,
})
);
});
});
};