diff --git a/local-cli/bundle/buildBundle.js b/local-cli/bundle/buildBundle.js
index 5b75ca3fb..10130e5a8 100644
--- a/local-cli/bundle/buildBundle.js
+++ b/local-cli/bundle/buildBundle.js
@@ -28,7 +28,6 @@ function buildBundle(args, config, output = outputBundle) {
getTransformOptionsModulePath: config.getTransformOptionsModulePath,
transformModulePath: args.transformer,
verbose: args.verbose,
- disableInternalTransforms: true,
};
const requestOpts = {
diff --git a/local-cli/bundle/output/bundle.js b/local-cli/bundle/output/bundle.js
index 6f40e5bac..e4247982f 100644
--- a/local-cli/bundle/output/bundle.js
+++ b/local-cli/bundle/output/bundle.js
@@ -17,14 +17,10 @@ function buildBundle(packagerClient, requestOptions) {
}
function createCodeWithMap(bundle, dev) {
- if (!dev) {
- return bundle.getMinifiedSourceAndMap(dev);
- } else {
- return {
- code: bundle.getSource({dev}),
- map: JSON.stringify(bundle.getSourceMap({dev})),
- };
- }
+ return {
+ code: bundle.getSource({dev}),
+ map: JSON.stringify(bundle.getSourceMap({dev})),
+ };
}
function saveBundleAndMap(bundle, options, log) {
@@ -53,7 +49,6 @@ function saveBundleAndMap(bundle, options, log) {
}
}
-
exports.build = buildBundle;
exports.save = saveBundleAndMap;
exports.formatName = 'bundle';
diff --git a/local-cli/dependencies/dependencies.js b/local-cli/dependencies/dependencies.js
index 8ada423cf..adc1e8897 100644
--- a/local-cli/dependencies/dependencies.js
+++ b/local-cli/dependencies/dependencies.js
@@ -63,7 +63,6 @@ function _dependencies(argv, config, resolve, reject) {
getTransformOptionsModulePath: config.getTransformOptionsModulePath,
transformModulePath: args.transformer,
verbose: config.verbose,
- disableInternalTransforms: true,
};
const relativePath = packageOpts.projectRoots.map(root =>
diff --git a/local-cli/server/util/attachHMRServer.js b/local-cli/server/util/attachHMRServer.js
index 362fdadf5..353b2aad3 100644
--- a/local-cli/server/util/attachHMRServer.js
+++ b/local-cli/server/util/attachHMRServer.js
@@ -32,6 +32,7 @@ function attachHMRServer({httpServer, path, packagerServer}) {
return packagerServer.getDependencies({
platform: platform,
dev: true,
+ hot: true,
entryFile: bundleEntry,
}).then(response => {
// for each dependency builds the object:
@@ -143,6 +144,7 @@ function attachHMRServer({httpServer, path, packagerServer}) {
return packagerServer.getDependencies({
platform: client.platform,
dev: true,
+ hot: true,
entryFile: filename,
recursive: true,
}).then(response => {
diff --git a/packager/package.json b/packager/package.json
index cf2306f0f..ab25c5cf2 100644
--- a/packager/package.json
+++ b/packager/package.json
@@ -1,5 +1,5 @@
{
- "version": "0.1.4",
+ "version": "0.2.0",
"name": "react-native-packager",
"description": "Build native apps with React!",
"repository": {
diff --git a/packager/react-packager/src/Bundler/Bundle.js b/packager/react-packager/src/Bundler/Bundle.js
index 9700af088..f42470272 100644
--- a/packager/react-packager/src/Bundler/Bundle.js
+++ b/packager/react-packager/src/Bundler/Bundle.js
@@ -11,53 +11,42 @@
const _ = require('underscore');
const base64VLQ = require('./base64-vlq');
const BundleBase = require('./BundleBase');
-const UglifyJS = require('uglify-js');
const ModuleTransport = require('../lib/ModuleTransport');
-const Activity = require('../Activity');
const crypto = require('crypto');
const SOURCEMAPPING_URL = '\n\/\/# sourceMappingURL=';
-const minifyCode = code =>
- UglifyJS.minify(code, {fromString: true, ascii_only: true}).code;
const getCode = x => x.code;
-const getMinifiedCode = x => minifyCode(x.code);
const getNameAndCode = ({name, code}) => ({name, code});
-const getNameAndMinifiedCode =
- ({name, code}) => ({name, code: minifyCode(code)});
class Bundle extends BundleBase {
- constructor(sourceMapUrl) {
+ constructor({sourceMapUrl, minify} = {}) {
super();
this._sourceMap = false;
this._sourceMapUrl = sourceMapUrl;
this._shouldCombineSourceMaps = false;
this._numPrependedModules = 0;
this._numRequireCalls = 0;
+ this._minify = minify;
}
- addModule(resolver, response, module, transformed) {
- return resolver.wrapModule(
- response,
+ addModule(resolver, resolutionResponse, module, moduleTransport) {
+ return resolver.wrapModule({
+ resolutionResponse,
module,
- transformed.code
- ).then(({code, name}) => {
- const moduleTransport = new ModuleTransport({
- code,
- name,
- map: transformed.map,
- sourceCode: transformed.sourceCode,
- sourcePath: transformed.sourcePath,
- virtual: transformed.virtual,
- });
-
+ name: moduleTransport.name,
+ code: moduleTransport.code,
+ map: moduleTransport.map,
+ meta: moduleTransport.meta,
+ minify: this._minify,
+ }).then(({code, map}) => {
// If we get a map from the transformer we'll switch to a mode
// were we're combining the source maps as opposed to
- if (!this._shouldCombineSourceMaps && moduleTransport.map != null) {
+ if (!this._shouldCombineSourceMaps && map != null) {
this._shouldCombineSourceMaps = true;
}
- super.addModule(moduleTransport);
+ super.addModule(new ModuleTransport({...moduleTransport, code, map}));
});
}
@@ -103,10 +92,6 @@ class Bundle extends BundleBase {
options = options || {};
- if (options.minify) {
- return this.getMinifiedSourceAndMap(options.dev).code;
- }
-
let source = super.getSource();
if (options.inlineSourceMap) {
@@ -118,84 +103,22 @@ class Bundle extends BundleBase {
return source;
}
- getUnbundle({minify}) {
- const allModules = super.getModules().slice();
+ getUnbundle() {
+ const allModules = this.getModules().slice();
const prependedModules = this._numPrependedModules;
const requireCalls = this._numRequireCalls;
const modules =
allModules
.splice(prependedModules, allModules.length - requireCalls - prependedModules);
- const startupCode =
- allModules
- .map(minify ? getMinifiedCode : getCode)
- .join('\n');
+ const startupCode = allModules.map(getCode).join('\n');
return {
startupCode,
- modules:
- modules.map(minify ? getNameAndMinifiedCode : getNameAndCode)
+ modules: modules.map(getNameAndCode)
};
}
- getMinifiedSourceAndMap(dev) {
- super.assertFinalized();
-
- if (this._minifiedSourceAndMap) {
- return this._minifiedSourceAndMap;
- }
-
- let source = this.getSource();
- let map = this.getSourceMap();
-
- if (!dev) {
- const wpoActivity = Activity.startEvent('Whole Program Optimisations');
- const wpoResult = require('babel-core').transform(source, {
- retainLines: true,
- compact: true,
- plugins: require('../transforms/whole-program-optimisations'),
- inputSourceMap: map,
- });
- Activity.endEvent(wpoActivity);
-
- source = wpoResult.code;
- map = wpoResult.map;
- }
-
- try {
- const minifyActivity = Activity.startEvent('minify');
- this._minifiedSourceAndMap = UglifyJS.minify(source, {
- fromString: true,
- outSourceMap: this._sourceMapUrl,
- inSourceMap: map,
- output: {ascii_only: true},
- });
- Activity.endEvent(minifyActivity);
- return this._minifiedSourceAndMap;
- } catch(e) {
- // Sometimes, when somebody is using a new syntax feature that we
- // don't yet have transform for, the untransformed line is sent to
- // uglify, and it chokes on it. This code tries to print the line
- // and the module for easier debugging
- let errorMessage = 'Error while minifying JS\n';
- if (e.line) {
- errorMessage += 'Transformed code line: "' +
- source.split('\n')[e.line - 1] + '"\n';
- }
- if (e.pos) {
- let fromIndex = source.lastIndexOf('__d(\'', e.pos);
- if (fromIndex > -1) {
- fromIndex += '__d(\''.length;
- const toIndex = source.indexOf('\'', fromIndex);
- errorMessage += 'Module name (best guess): ' +
- source.substring(fromIndex, toIndex) + '\n';
- }
- }
- errorMessage += e.toString();
- throw new Error(errorMessage);
- }
- }
-
/**
* I found a neat trick in the sourcemap spec that makes it easy
* to concat sourcemaps. The `sections` field allows us to combine
@@ -211,14 +134,17 @@ class Bundle extends BundleBase {
};
let line = 0;
- super.getModules().forEach(function(module) {
+ this.getModules().forEach(module => {
let map = module.map;
+
if (module.virtual) {
map = generateSourceMapForVirtualModule(module);
}
if (options.excludeSource) {
- map = _.extend({}, map, {sourcesContent: []});
+ if (map.sourcesContent && map.sourcesContent.length) {
+ map = _.extend({}, map, {sourcesContent: []});
+ }
}
result.sections.push({
@@ -234,25 +160,20 @@ class Bundle extends BundleBase {
getSourceMap(options) {
super.assertFinalized();
- options = options || {};
-
- if (options.minify) {
- return this.getMinifiedSourceAndMap(options.dev).map;
- }
-
if (this._shouldCombineSourceMaps) {
return this._getCombinedSourceMaps(options);
}
const mappings = this._getMappings();
+ const modules = this.getModules();
const map = {
file: this._getSourceMapFile(),
- sources: _.pluck(super.getModules(), 'sourcePath'),
+ sources: modules.map(module => module.sourcePath),
version: 3,
names: [],
mappings: mappings,
sourcesContent: options.excludeSource
- ? [] : _.pluck(super.getModules(), 'sourceCode')
+ ? [] : modules.map(module => module.sourceCode)
};
return map;
}
@@ -316,12 +237,10 @@ class Bundle extends BundleBase {
}
getJSModulePaths() {
- return super.getModules().filter(function(module) {
+ return this.getModules()
// Filter out non-js files. Like images etc.
- return !module.virtual;
- }).map(function(module) {
- return module.sourcePath;
- });
+ .filter(module => !module.virtual)
+ .map(module => module.sourcePath);
}
getDebugInfo() {
@@ -338,7 +257,7 @@ class Bundle extends BundleBase {
'}',
'',
'
Module paths and transformed code:
',
- super.getModules().map(function(m) {
+ this.getModules().map(function(m) {
return ' Path:
' + m.sourcePath + '
Source:
' +
'
' +
_.escape(m.code) + ' ';
@@ -354,15 +273,17 @@ class Bundle extends BundleBase {
sourceMapUrl: this._sourceMapUrl,
numPrependedModules: this._numPrependedModules,
numRequireCalls: this._numRequireCalls,
+ shouldCombineSourceMaps: this._shouldCombineSourceMaps,
};
}
static fromJSON(json) {
- const bundle = new Bundle(json.sourceMapUrl);
+ const bundle = new Bundle({sourceMapUrl: json.sourceMapUrl});
bundle._sourceMapUrl = json.sourceMapUrl;
bundle._numPrependedModules = json.numPrependedModules;
bundle._numRequireCalls = json.numRequireCalls;
+ bundle._shouldCombineSourceMaps = json.shouldCombineSourceMaps;
BundleBase.fromJSON(bundle, json);
diff --git a/packager/react-packager/src/Bundler/HMRBundle.js b/packager/react-packager/src/Bundler/HMRBundle.js
index 728507788..d9725eea1 100644
--- a/packager/react-packager/src/Bundler/HMRBundle.js
+++ b/packager/react-packager/src/Bundler/HMRBundle.js
@@ -21,21 +21,14 @@ class HMRBundle extends BundleBase {
this._sourceMappingURLs = [];
}
- addModule(resolver, response, module, transformed) {
- return resolver.resolveRequires(response,
+ addModule(resolver, response, module, moduleTransport) {
+ return resolver.resolveRequires(
+ response,
module,
- transformed.code,
- ).then(({name, code}) => {
- const moduleTransport = new ModuleTransport({
- code,
- name,
- map: transformed.map,
- sourceCode: transformed.sourceCode,
- sourcePath: transformed.sourcePath,
- virtual: transformed.virtual,
- });
-
- super.addModule(moduleTransport);
+ moduleTransport.code,
+ moduleTransport.meta.dependencyOffsets,
+ ).then(code => {
+ super.addModule(new ModuleTransport({...moduleTransport, code}));
this._sourceMappingURLs.push(this._sourceMappingURLFn(moduleTransport.sourcePath));
this._sourceURLs.push(this._sourceURLFn(moduleTransport.sourcePath));
});
diff --git a/packager/react-packager/src/Bundler/__tests__/Bundle-test.js b/packager/react-packager/src/Bundler/__tests__/Bundle-test.js
index 23fe5762d..87a5a432f 100644
--- a/packager/react-packager/src/Bundler/__tests__/Bundle-test.js
+++ b/packager/react-packager/src/Bundler/__tests__/Bundle-test.js
@@ -11,17 +11,15 @@
jest.autoMockOff();
const Bundle = require('../Bundle');
-const ModuleTransport = require('../../lib/ModuleTransport');
const Promise = require('Promise');
const SourceMapGenerator = require('source-map').SourceMapGenerator;
-const UglifyJS = require('uglify-js');
const crypto = require('crypto');
describe('Bundle', () => {
var bundle;
beforeEach(() => {
- bundle = new Bundle('test_url');
+ bundle = new Bundle({sourceMapUrl: 'test_url'});
bundle.getSourceMap = jest.genMockFn().mockImpl(() => {
return 'test-source-map';
});
@@ -108,34 +106,11 @@ describe('Bundle', () => {
].join('\n'));
});
});
-
- pit('should get minified source', () => {
- const minified = {
- code: 'minified',
- map: 'map',
- };
-
- UglifyJS.minify = function() {
- return minified;
- };
-
- return Promise.resolve().then(() => {
- return addModule({
- bundle,
- code: 'transformed foo;',
- sourceCode: 'source foo',
- sourcePath: 'foo path',
- });
- }).then(() => {
- bundle.finalize();
- expect(bundle.getMinifiedSourceAndMap({dev: true})).toBe(minified);
- });
- });
});
describe('sourcemap bundle', () => {
pit('should create sourcemap', () => {
- const otherBundle = new Bundle('test_url');
+ const otherBundle = new Bundle({sourceMapUrl: 'test_url'});
return Promise.resolve().then(() => {
return addModule({
@@ -179,7 +154,7 @@ describe('Bundle', () => {
});
pit('should combine sourcemaps', () => {
- const otherBundle = new Bundle('test_url');
+ const otherBundle = new Bundle({sourceMapUrl: 'test_url'});
return Promise.resolve().then(() => {
return addModule({
@@ -269,7 +244,7 @@ describe('Bundle', () => {
describe('getAssets()', () => {
it('should save and return asset objects', () => {
- var p = new Bundle('test_url');
+ var p = new Bundle({sourceMapUrl: 'test_url'});
var asset1 = {};
var asset2 = {};
p.addAsset(asset1);
@@ -281,7 +256,7 @@ describe('Bundle', () => {
describe('getJSModulePaths()', () => {
pit('should return module paths', () => {
- var otherBundle = new Bundle('test_url');
+ var otherBundle = new Bundle({sourceMapUrl: 'test_url'});
return Promise.resolve().then(() => {
return addModule({
bundle: otherBundle,
@@ -305,7 +280,7 @@ describe('Bundle', () => {
describe('getEtag()', function() {
it('should return an etag', function() {
- var bundle = new Bundle('test_url');
+ var bundle = new Bundle({sourceMapUrl: 'test_url'});
bundle.finalize({});
var eTag = crypto.createHash('md5').update(bundle.getSource()).digest('hex');
expect(bundle.getEtag()).toEqual(eTag);
@@ -365,19 +340,17 @@ function genSourceMap(modules) {
return sourceMapGen.toJSON();
}
-function resolverFor(code) {
+function resolverFor(code, map) {
return {
- wrapModule: (response, module, sourceCode) => Promise.resolve(
- {name: 'name', code}
- ),
+ wrapModule: () => Promise.resolve({code, map}),
};
}
function addModule({bundle, code, sourceCode, sourcePath, map, virtual}) {
return bundle.addModule(
- resolverFor(code),
+ resolverFor(code, map),
null,
null,
- {sourceCode, sourcePath, map, virtual}
+ {code, sourceCode, sourcePath, map, virtual}
);
}
diff --git a/packager/react-packager/src/Bundler/__tests__/Bundler-test.js b/packager/react-packager/src/Bundler/__tests__/Bundler-test.js
index 1c72d0a42..e108177e2 100644
--- a/packager/react-packager/src/Bundler/__tests__/Bundler-test.js
+++ b/packager/react-packager/src/Bundler/__tests__/Bundler-test.js
@@ -19,7 +19,6 @@ jest
jest.mock('fs');
var Bundler = require('../');
-var JSTransformer = require('../../JSTransformer');
var Resolver = require('../../Resolver');
var sizeOf = require('image-size');
var fs = require('fs');
@@ -43,25 +42,29 @@ describe('Bundler', function() {
isJSON() { return isJSON; },
isAsset() { return isAsset; },
isAsset_DEPRECATED() { return isAsset_DEPRECATED; },
+ read: () => ({
+ code: 'arbitrary',
+ source: 'arbitrary',
+ }),
};
}
var getDependencies;
var getModuleSystemDependencies;
- var wrapModule;
var bundler;
var assetServer;
var modules;
+ var projectRoots;
beforeEach(function() {
getDependencies = jest.genMockFn();
getModuleSystemDependencies = jest.genMockFn();
- wrapModule = jest.genMockFn();
+ projectRoots = ['/root'];
+
Resolver.mockImpl(function() {
return {
getDependencies: getDependencies,
getModuleSystemDependencies: getModuleSystemDependencies,
- wrapModule: wrapModule,
};
});
@@ -80,7 +83,7 @@ describe('Bundler', function() {
};
bundler = new Bundler({
- projectRoots: ['/root'],
+ projectRoots,
assetServer: assetServer,
});
@@ -109,34 +112,18 @@ describe('Bundler', function() {
}),
];
- getDependencies.mockImpl(function() {
- return Promise.resolve({
+ getDependencies.mockImpl((main, options, transformOptions) =>
+ Promise.resolve({
mainModuleId: 'foo',
- dependencies: modules
- });
- });
+ dependencies: modules,
+ transformOptions,
+ })
+ );
getModuleSystemDependencies.mockImpl(function() {
return [];
});
- JSTransformer.prototype.loadFileAndTransform
- .mockImpl(function(path) {
- return Promise.resolve({
- code: 'transformed ' + path,
- map: 'sourcemap ' + path,
- sourceCode: 'source ' + path,
- sourcePath: path
- });
- });
-
- wrapModule.mockImpl(function(response, module, code) {
- return module.getName().then(name => ({
- name,
- code: 'lol ' + code + ' lol'
- }));
- });
-
sizeOf.mockImpl(function(path, cb) {
cb(null, { width: 50, height: 100 });
});
@@ -207,10 +194,20 @@ describe('Bundler', function() {
});
pit('gets the list of dependencies from the resolver', function() {
- return bundler.getDependencies('/root/foo.js', true).then(() =>
+ const entryFile = '/root/foo.js';
+ return bundler.getDependencies({entryFile, recursive: true}).then(() =>
expect(getDependencies).toBeCalledWith(
'/root/foo.js',
{ dev: true, recursive: true },
+ { minify: false,
+ dev: true,
+ transform: {
+ dev: true,
+ hot: false,
+ projectRoots,
+ }
+ },
+ undefined,
)
);
});
diff --git a/packager/react-packager/src/Bundler/index.js b/packager/react-packager/src/Bundler/index.js
index 9da681d65..3c1c426df 100644
--- a/packager/react-packager/src/Bundler/index.js
+++ b/packager/react-packager/src/Bundler/index.js
@@ -26,7 +26,6 @@ const imageSize = require('image-size');
const version = require('../../../../package.json').version;
const sizeOf = Promise.denodeify(imageSize);
-const readFile = Promise.denodeify(fs.readFile);
const noop = () => {};
@@ -82,10 +81,6 @@ const validateOpts = declareOpts({
type: 'number',
required: false,
},
- disableInternalTransforms: {
- type: 'boolean',
- default: false,
- },
});
class Bundler {
@@ -123,6 +118,10 @@ class Bundler {
cacheKey: cacheKeyParts.join('$'),
});
+ this._transformer = new Transformer({
+ transformModulePath: opts.transformModulePath,
+ });
+
this._resolver = new Resolver({
projectRoots: opts.projectRoots,
blacklistRE: opts.blacklistRE,
@@ -132,14 +131,10 @@ class Bundler {
fileWatcher: opts.fileWatcher,
assetExts: opts.assetExts,
cache: this._cache,
- });
-
- this._transformer = new Transformer({
- projectRoots: opts.projectRoots,
- blacklistRE: opts.blacklistRE,
- cache: this._cache,
- transformModulePath: opts.transformModulePath,
- disableInternalTransforms: opts.disableInternalTransforms,
+ transformCode:
+ (module, code, options) =>
+ this._transformer.transformFile(module.path, code, options),
+ minifyCode: this._transformer.minify,
});
this._projectRoots = opts.projectRoots;
@@ -158,11 +153,11 @@ class Bundler {
}
bundle(options) {
- const {dev, unbundle, platform} = options;
+ const {dev, minify, unbundle} = options;
const moduleSystemDeps =
- this._resolver.getModuleSystemDependencies({dev, unbundle, platform});
+ this._resolver.getModuleSystemDependencies({dev, unbundle});
return this._bundle({
- bundle: new Bundle(options.sourceMapUrl),
+ bundle: new Bundle({minify, sourceMapUrl: options.sourceMapUrl}),
moduleSystemDeps,
...options,
});
@@ -230,7 +225,8 @@ class Bundler {
entryFile,
runModule: runMainModule,
runBeforeMainModule,
- dev: isDev,
+ dev,
+ minify,
platform,
moduleSystemDeps = [],
hot,
@@ -264,7 +260,8 @@ class Bundler {
return this._buildBundle({
entryFile,
- isDev,
+ dev,
+ minify,
platform,
bundle,
hot,
@@ -279,7 +276,7 @@ class Bundler {
runModule: runMainModule,
runBeforeMainModule,
sourceMapUrl,
- dev: isDev,
+ dev,
platform,
}) {
const onModuleTransformed = ({module, transformed, response, bundle}) => {
@@ -303,17 +300,19 @@ class Bundler {
return this._buildBundle({
entryFile,
- isDev,
+ dev,
platform,
onModuleTransformed,
finalizeBundle,
+ minify: false,
bundle: new PrepackBundle(sourceMapUrl),
});
}
_buildBundle({
entryFile,
- isDev,
+ dev,
+ minify,
platform,
bundle,
hot,
@@ -323,54 +322,54 @@ class Bundler {
finalizeBundle = noop,
}) {
const findEventId = Activity.startEvent('find dependencies');
+
if (!resolutionResponse) {
- resolutionResponse = this.getDependencies(entryFile, isDev, platform);
+ let onProgess;
+ if (process.stdout.isTTY) {
+ const bar = new ProgressBar(
+ 'transformed :current/:total (:percent)',
+ {complete: '=', incomplete: ' ', width: 40, total: 1},
+ );
+ onProgess = (_, total) => {
+ bar.total = total;
+ bar.tick();
+ };
+ }
+
+ resolutionResponse = this.getDependencies(
+ {entryFile, dev, platform, hot, onProgess, minify});
}
return Promise.resolve(resolutionResponse).then(response => {
Activity.endEvent(findEventId);
onResolutionResponse(response);
- const transformEventId = Activity.startEvent('transform');
- const bar = process.stdout.isTTY
- ? new ProgressBar('transforming [:bar] :percent :current/:total', {
- complete: '=',
- incomplete: ' ',
- width: 40,
- total: response.dependencies.length,
- })
- : {tick() {}};
- const transformPromises =
- response.dependencies.map(module =>
- this._transformModule({
- mainModuleName: response.mainModuleId,
- bundle,
+ const toModuleTransport = module =>
+ this._toModuleTransport({
+ module,
+ bundle,
+ transformOptions: response.transformOptions,
+ }).then(transformed => {
+ onModuleTransformed({
module,
- platform,
- dev: isDev,
- hot
- }).then(transformed => {
- bar.tick();
- onModuleTransformed({module, transformed, response, bundle});
- return {module, transformed};
- })
+ response,
+ bundle,
+ transformed,
+ });
+ return {module, transformed};
+ });
+
+ return Promise.all(response.dependencies.map(toModuleTransport))
+ .then(transformedModules =>
+ Promise
+ .resolve(finalizeBundle({bundle, transformedModules, response}))
+ .then(() => bundle)
);
- return Promise.all(transformPromises).then(transformedModules => {
- Activity.endEvent(transformEventId);
- return Promise
- .resolve(finalizeBundle({bundle, transformedModules, response}))
- .then(() => bundle);
- });
});
}
invalidateFile(filePath) {
- if (this._transformOptionsModule) {
- this._transformOptionsModule.onFileChange &&
- this._transformOptionsModule.onFileChange();
- }
-
- this._transformer.invalidateFile(filePath);
+ this._cache.invalidate(filePath);
}
getShallowDependencies(entryFile) {
@@ -385,19 +384,35 @@ class Bundler {
return this._resolver.getModuleForPath(entryFile);
}
- getDependencies(main, isDev, platform, recursive = true) {
- return this._resolver.getDependencies(
- main,
- {
- dev: isDev,
+ getDependencies({
+ entryFile,
+ platform,
+ dev = true,
+ minify = !dev,
+ hot = false,
+ recursive = true,
+ onProgess,
+ }) {
+ return this.getTransformOptions(
+ entryFile, {dev, platform, hot, projectRoots: this._projectRoots}
+ ).then(transformSpecificOptions => {
+ const transformOptions = {
+ minify,
+ dev,
platform,
- recursive,
- },
- );
+ transform: transformSpecificOptions,
+ };
+ return this._resolver.getDependencies(
+ entryFile,
+ {dev, platform, recursive},
+ transformOptions,
+ onProgess,
+ );
+ });
}
getOrderedDependencyPaths({ entryFile, dev, platform }) {
- return this.getDependencies(entryFile, dev, platform).then(
+ return this.getDependencies({entryFile, dev, platform}).then(
({ dependencies }) => {
const ret = [];
const promises = [];
@@ -428,36 +443,32 @@ class Bundler {
);
}
- _transformModule({
- bundle,
- module,
- mainModuleName,
- platform = null,
- dev = true,
- hot = false,
- }) {
+ _toModuleTransport({module, bundle, transformOptions}) {
+ let moduleTransport;
if (module.isAsset_DEPRECATED()) {
- return this._generateAssetModule_DEPRECATED(bundle, module);
+ moduleTransport = this._generateAssetModule_DEPRECATED(bundle, module);
} else if (module.isAsset()) {
- return this._generateAssetModule(bundle, module, platform);
- } else if (module.isJSON()) {
- return generateJSONModule(module);
- } else {
- return this._getTransformOptions(
- {
- bundleEntry: mainModuleName,
- platform: platform,
- dev: dev,
- modulePath: module.path,
- },
- {hot},
- ).then(options => {
- return this._transformer.loadFileAndTransform(
- path.resolve(module.path),
- options,
- );
- });
+ moduleTransport = this._generateAssetModule(
+ bundle, module, transformOptions.platform);
}
+
+ if (moduleTransport) {
+ return Promise.resolve(moduleTransport);
+ }
+
+ return Promise.all([
+ module.getName(),
+ module.read(transformOptions),
+ ]).then((
+ [name, {code, dependencies, dependencyOffsets, map, source}]
+ ) => new ModuleTransport({
+ name,
+ code,
+ map,
+ meta: {dependencies, dependencyOffsets},
+ sourceCode: source,
+ sourcePath: module.path
+ }));
}
getGraphDebugInfo() {
@@ -480,9 +491,10 @@ class Bundler {
bundle.addAsset(img);
- const code = 'module.exports = ' + JSON.stringify(img) + ';';
+ const code = 'module.exports=' + JSON.stringify(img) + ';';
return new ModuleTransport({
+ name: id,
code: code,
sourceCode: code,
sourcePath: module.path,
@@ -525,19 +537,31 @@ class Bundler {
type: assetData.type,
};
- const ASSET_TEMPLATE = 'module.exports = require("AssetRegistry").registerAsset(%json);';
- const code = ASSET_TEMPLATE.replace('%json', JSON.stringify(asset));
+ const json = JSON.stringify(asset);
+ const code =
+ `module.exports = require('AssetRegistry').registerAsset(${json});`;
+ const dependencies = ['AssetRegistry'];
+ const dependencyOffsets = [code.indexOf('AssetRegistry') - 1];
- return {asset, code};
+ return {
+ asset,
+ code,
+ meta: {dependencies, dependencyOffsets}
+ };
});
}
_generateAssetModule(bundle, module, platform = null) {
- return this._generateAssetObjAndCode(module, platform).then(({asset, code}) => {
+ return Promise.all([
+ module.getName(),
+ this._generateAssetObjAndCode(module, platform),
+ ]).then(([name, {asset, code, meta}]) => {
bundle.addAsset(asset);
return new ModuleTransport({
- code: code,
+ name,
+ code,
+ meta,
sourceCode: code,
sourcePath: module.path,
virtual: true,
@@ -545,37 +569,15 @@ class Bundler {
});
}
- _getTransformOptions(config, options) {
- const transformerOptions = this._transformOptionsModule
- ? this._transformOptionsModule.get(Object.assign(
- {
- bundler: this,
- platform: options.platform,
- dev: options.dev,
- },
- config,
- ))
- : Promise.resolve(null);
-
- return transformerOptions.then(overrides => {
- return {...options, ...overrides};
- });
+ getTransformOptions(mainModuleName, options) {
+ const extraOptions = this._transformOptionsModule
+ ? this._transformOptionsModule(mainModuleName, options, this)
+ : null;
+ return Promise.resolve(extraOptions)
+ .then(extraOptions => Object.assign(options, extraOptions));
}
}
-function generateJSONModule(module) {
- return readFile(module.path).then(function(data) {
- const code = 'module.exports = ' + data.toString('utf8') + ';';
-
- return new ModuleTransport({
- code: code,
- sourceCode: code,
- sourcePath: module.path,
- virtual: true,
- });
- });
-}
-
function getPathRelativeToRoot(roots, absPath) {
for (let i = 0; i < roots.length; i++) {
const relPath = path.relative(roots[i], absPath);
@@ -594,12 +596,4 @@ function verifyRootExists(root) {
assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory');
}
-class DummyCache {
- get(filepath, field, loaderCb) {
- return loaderCb();
- }
-
- end(){}
- invalidate(filepath){}
-}
module.exports = Bundler;
diff --git a/packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js b/packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js
index cd73549c8..dc93a872f 100644
--- a/packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js
+++ b/packager/react-packager/src/JSTransformer/__tests__/Transformer-test.js
@@ -12,61 +12,66 @@ jest
.dontMock('../../lib/ModuleTransport')
.dontMock('../');
-jest.mock('fs');
-jest.setMock('temp', {path: () => '/arbitrary/path'});
+const fs = {writeFileSync: jest.genMockFn()};
+const temp = {path: () => '/arbitrary/path'};
+const workerFarm = jest.genMockFn();
+jest.setMock('fs', fs);
+jest.setMock('temp', temp);
+jest.setMock('worker-farm', workerFarm);
var Transformer = require('../');
-var fs = require('fs');
-var Cache;
-var options;
+const {any} = jasmine;
describe('Transformer', function() {
- var workers;
+ let options, workers, Cache;
+ const fileName = '/an/arbitrary/file.js';
+ const transformModulePath = __filename;
beforeEach(function() {
Cache = jest.genMockFn();
Cache.prototype.get = jest.genMockFn().mockImpl((a, b, c) => c());
- workers = jest.genMockFn();
- jest.setMock('worker-farm', jest.genMockFn().mockImpl(function() {
- return workers;
- }));
-
- options = {
- transformModulePath: '/foo/bar',
- cache: new Cache({}),
- };
+ fs.writeFileSync.mockClear();
+ options = {transformModulePath};
+ workerFarm.mockClear();
+ workerFarm.mockImpl((opts, path, methods) => {
+ const api = workers = {};
+ methods.forEach(method => api[method] = jest.genMockFn());
+ return api;
+ });
});
- pit('should loadFileAndTransform', function() {
- workers.mockImpl(function(data, callback) {
- callback(null, { code: 'transformed', map: 'sourceMap' });
- });
- fs.readFile.mockImpl(function(file, callback) {
- callback(null, 'content');
+ it('passes transform module path, file path, source code, and options to the worker farm when transforming', () => {
+ const transformOptions = {arbitrary: 'options'};
+ const code = 'arbitrary(code)';
+ new Transformer(options).transformFile(fileName, code, transformOptions);
+ expect(workers.transformAndExtractDependencies).toBeCalledWith(
+ transformModulePath,
+ fileName,
+ code,
+ transformOptions,
+ any(Function),
+ );
+ });
+
+ pit('passes the data produced by the worker back', () => {
+ const transformer = new Transformer(options);
+ const result = { code: 'transformed', map: 'sourceMap' };
+ workers.transformAndExtractDependencies.mockImpl(function(transformPath, filename, code, options, callback) {
+ callback(null, result);
});
- return new Transformer(options).loadFileAndTransform('file')
- .then(function(data) {
- expect(data).toEqual({
- code: 'transformed',
- map: 'sourceMap',
- sourcePath: 'file',
- sourceCode: 'content'
- });
- });
+ return transformer.transformFile(fileName, '', {})
+ .then(data => expect(data).toBe(result));
});
pit('should add file info to parse errors', function() {
+ const transformer = new Transformer(options);
var message = 'message';
var snippet = 'snippet';
- fs.readFile.mockImpl(function(file, callback) {
- callback(null, 'var x;\nvar answer = 1 = x;');
- });
-
- workers.mockImpl(function(data, callback) {
+ workers.transformAndExtractDependencies.mockImpl(function(transformPath, filename, code, options, callback) {
var babelError = new SyntaxError(message);
babelError.type = 'SyntaxError';
babelError.description = message;
@@ -78,13 +83,13 @@ describe('Transformer', function() {
callback(babelError);
});
- return new Transformer(options).loadFileAndTransform('foo-file.js')
+ return transformer.transformFile(fileName, '', {})
.catch(function(error) {
expect(error.type).toEqual('TransformError');
expect(error.message).toBe('SyntaxError ' + message);
expect(error.lineNumber).toBe(2);
expect(error.column).toBe(15);
- expect(error.filename).toBe('foo-file.js');
+ expect(error.filename).toBe(fileName);
expect(error.description).toBe(message);
expect(error.snippet).toBe(snippet);
});
diff --git a/packager/react-packager/src/JSTransformer/__tests__/worker-test.js b/packager/react-packager/src/JSTransformer/__tests__/worker-test.js
deleted file mode 100644
index f81907c2c..000000000
--- a/packager/react-packager/src/JSTransformer/__tests__/worker-test.js
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * 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';
-
-jest.autoMockOff();
-
-jest.mock('babel-core');
-
-const worker = require('../worker');
-const babel = require('babel-core');
-
-const code = 'code';
-
-describe('Resolver', function() {
- beforeEach(() => {
- babel.transform.mockImpl((source, options) => source);
- });
-
- describe('when no external transform is provided', () => {
- xit('should invoke internal transform if available', () => {
- transform({
- sourceCode: 'code',
- filename: 'test',
- options: options({opts: {}, internalTransformsEnabled: true}),
- });
- expect(babel.transform.mock.calls.length).toBe(1);
- });
-
- it('should not invoke internal transform if unavailable', () => {
- transform({
- sourceCode: 'code',
- filename: 'test',
- options: options({opts: {}, internalTransformsEnabled: false}),
- });
- expect(babel.transform.mock.calls.length).toBe(0);
- });
- });
-
- describe('when external transform is provided', () => {
- xit('should invoke both transformers if internal is available', () => {
- transform({
- sourceCode: code,
- filename: 'test',
- options: options({
- opts: {
- externalTransformModulePath: require.resolve(
- '../../../../transformer.js'
- ),
- },
- internalTransformsEnabled: true,
- }),
- });
- expect(babel.transform.mock.calls.length).toBe(2);
- });
-
- it('should invoke only external transformer if internal is not available', () => {
- transform({
- sourceCode: 'code',
- filename: 'test',
- options: options({
- opts: {
- externalTransformModulePath: require.resolve(
- '../../../../transformer.js'
- ),
- },
- internalTransformsEnabled: false,
- }),
- });
- expect(babel.transform.mock.calls.length).toBe(1);
- });
-
- xit('should pipe errors through transform pipeline', () => {
- const error = new Error('transform error');
- babel.transform.mockImpl((source, options) => {
- throw error;
- });
-
- const callback = transform({
- sourceCode: 'code',
- filename: 'test',
- options: options({
- opts: {
- externalTransformModulePath: require.resolve(
- '../../../../transformer.js'
- ),
- },
- internalTransformsEnabled: true,
- }),
- });
- expect(callback.mock.calls[0][0]).toBe(error);
- });
- });
-});
-
-function transform(data) {
- const callback = jest.genMockFunction();
- worker(data, callback);
- return callback;
-}
-
-function options({opts, internalTransformsEnabled}) {
- return Object.assign(opts, {hot: internalTransformsEnabled});
-}
diff --git a/packager/react-packager/src/JSTransformer/index.js b/packager/react-packager/src/JSTransformer/index.js
index a25cd57d9..3ddd95bdf 100644
--- a/packager/react-packager/src/JSTransformer/index.js
+++ b/packager/react-packager/src/JSTransformer/index.js
@@ -8,18 +8,13 @@
*/
'use strict';
-const ModuleTransport = require('../lib/ModuleTransport');
const Promise = require('promise');
const declareOpts = require('../lib/declareOpts');
-const fs = require('fs');
const os = require('os');
-const temp = require('temp');
const util = require('util');
const workerFarm = require('worker-farm');
const debug = require('debug')('ReactNativePackager:JStransformer');
-const readFile = Promise.denodeify(fs.readFile);
-
// Avoid memory leaks caused in workers. This number seems to be a good enough number
// to avoid any memory leak while not slowing down initial builds.
// TODO(amasad): Once we get bundle splitting, we can drive this down a bit more.
@@ -32,33 +27,14 @@ const DEFAULT_MAX_CALL_TIME = 301000;
const MAX_RETRIES = 2;
const validateOpts = declareOpts({
- projectRoots: {
- type: 'array',
- required: true,
- },
- blacklistRE: {
- type: 'object', // typeof regex is object
- },
- polyfillModuleNames: {
- type: 'array',
- default: [],
- },
transformModulePath: {
type:'string',
required: false,
},
- cache: {
- type: 'object',
- required: true,
- },
transformTimeoutInterval: {
type: 'number',
default: DEFAULT_MAX_CALL_TIME,
},
- disableInternalTransforms: {
- type: 'boolean',
- default: false,
- },
});
const maxConcurrentWorkers = ((cores, override) => {
@@ -82,120 +58,67 @@ class Transformer {
constructor(options) {
const opts = this._opts = validateOpts(options);
- this._cache = opts.cache;
- this._transformModulePath = opts.transformModulePath;
- this._projectRoots = opts.projectRoots;
+ const {transformModulePath} = opts;
- if (opts.transformModulePath != null) {
- let transformer;
+ if (transformModulePath) {
+ this._transformModulePath = require.resolve(transformModulePath);
- if (opts.disableInternalTransforms) {
- transformer = opts.transformModulePath;
- } else {
- transformer = this._workerWrapperPath = temp.path();
- fs.writeFileSync(
- this._workerWrapperPath,
- `
- module.exports = require(${JSON.stringify(require.resolve('./worker'))});
- require(${JSON.stringify(String(opts.transformModulePath))});
- `
- );
- }
+ this._workers = workerFarm(
+ {
+ autoStart: true,
+ maxConcurrentCallsPerWorker: 1,
+ maxConcurrentWorkers: maxConcurrentWorkers,
+ maxCallsPerWorker: MAX_CALLS_PER_WORKER,
+ maxCallTime: opts.transformTimeoutInterval,
+ maxRetries: MAX_RETRIES,
+ },
+ require.resolve('./worker'),
+ ['minify', 'transformAndExtractDependencies']
+ );
- this._workers = workerFarm({
- autoStart: true,
- maxConcurrentCallsPerWorker: 1,
- maxConcurrentWorkers: maxConcurrentWorkers,
- maxCallsPerWorker: MAX_CALLS_PER_WORKER,
- maxCallTime: opts.transformTimeoutInterval,
- maxRetries: MAX_RETRIES,
- }, transformer);
-
- this._transform = Promise.denodeify(this._workers);
+ this._transform = Promise.denodeify(this._workers.transformAndExtractDependencies);
+ this.minify = Promise.denodeify(this._workers.minify);
}
}
kill() {
this._workers && workerFarm.end(this._workers);
- if (this._workerWrapperPath &&
- typeof this._workerWrapperPath === 'string') {
- fs.unlink(this._workerWrapperPath, () => {}); // we don't care about potential errors here
- }
}
- invalidateFile(filePath) {
- this._cache.invalidate(filePath);
- }
-
- loadFileAndTransform(filePath, options) {
- if (this._transform == null) {
+ transformFile(fileName, code, options) {
+ if (!this._transform) {
return Promise.reject(new Error('No transfrom module'));
}
+ debug('transforming file', fileName);
+ return this
+ ._transform(this._transformModulePath, fileName, code, options)
+ .then(result => {
+ debug('done transforming file', fileName);
+ return result;
+ })
+ .catch(error => {
+ if (error.type === 'TimeoutError') {
+ const timeoutErr = new Error(
+ `TimeoutError: transforming ${fileName} took longer than ` +
+ `${this._opts.transformTimeoutInterval / 1000} seconds.\n` +
+ `You can adjust timeout via the 'transformTimeoutInterval' option`
+ );
+ timeoutErr.type = 'TimeoutError';
+ throw timeoutErr;
+ } else if (error.type === 'ProcessTerminatedError') {
+ const uncaughtError = new Error(
+ 'Uncaught error in the transformer worker: ' +
+ this._opts.transformModulePath
+ );
+ uncaughtError.type = 'ProcessTerminatedError';
+ throw uncaughtError;
+ }
- debug('transforming file', filePath);
-
- const optionsJSON = JSON.stringify(options);
-
- return this._cache.get(
- filePath,
- 'transformedSource-' + optionsJSON,
- // TODO: use fastfs to avoid reading file from disk again
- () => readFile(filePath).then(
- buffer => {
- const sourceCode = buffer.toString('utf8');
-
- return this._transform({
- sourceCode,
- filename: filePath,
- options: {
- ...options,
- projectRoots: this._projectRoots,
- externalTransformModulePath: this._transformModulePath,
- },
- }).then(res => {
- if (res.error) {
- console.warn(
- 'Error property on the result value from the transformer',
- 'module is deprecated and will be removed in future versions.',
- 'Please pass an error object as the first argument to the callback'
- );
- throw formatError(res.error, filePath);
- }
-
- debug('done transforming file', filePath);
-
- return new ModuleTransport({
- code: res.code,
- map: res.map,
- sourcePath: filePath,
- sourceCode: sourceCode,
- });
- }).catch(err => {
- if (err.type === 'TimeoutError') {
- const timeoutErr = new Error(
- `TimeoutError: transforming ${filePath} took longer than ` +
- `${this._opts.transformTimeoutInterval / 1000} seconds.\n` +
- `You can adjust timeout via the 'transformTimeoutInterval' option`
- );
- timeoutErr.type = 'TimeoutError';
- throw timeoutErr;
- } else if (err.type === 'ProcessTerminatedError') {
- const uncaughtError = new Error(
- 'Uncaught error in the transformer worker: ' +
- this._opts.transformModulePath
- );
- uncaughtError.type = 'ProcessTerminatedError';
- throw uncaughtError;
- }
-
- throw formatError(err, filePath);
- });
- })
- );
+ throw formatError(error, fileName);
+ });
}
}
-
module.exports = Transformer;
Transformer.TransformError = TransformError;
diff --git a/packager/react-packager/src/JSTransformer/worker.js b/packager/react-packager/src/JSTransformer/worker.js
deleted file mode 100644
index c8d388a41..000000000
--- a/packager/react-packager/src/JSTransformer/worker.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * 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';
-
-var babel = require('babel-core');
-var makeInternalConfig = require('babel-preset-react-native/configs/internal');
-
-// Runs internal transforms on the given sourceCode. Note that internal
-// transforms should be run after the external ones to ensure that they run on
-// Javascript code
-function internalTransforms(sourceCode, filename, options) {
- var internalBabelConfig = makeInternalConfig(options);
-
- if (!internalBabelConfig) {
- return {
- code: sourceCode,
- filename: filename,
- };
- }
-
- var result = babel.transform(sourceCode, Object.assign({
- filename: filename,
- sourceFileName: filename,
- }, internalBabelConfig));
-
- return {
- code: result.code,
- filename: filename,
- };
-}
-
-function onExternalTransformDone(data, callback, error, externalOutput) {
- if (error) {
- callback(error);
- return;
- }
-
- var result = internalTransforms(
- externalOutput.code,
- externalOutput.filename,
- data.options
- );
-
- callback(null, result);
-}
-
-module.exports = function(data, callback) {
- try {
- if (data.options.externalTransformModulePath) {
- var externalTransformModule = require(
- data.options.externalTransformModulePath
- );
- externalTransformModule(
- data,
- onExternalTransformDone.bind(null, data, callback)
- );
- } else {
- onExternalTransformDone(
- data,
- callback,
- null,
- {
- code: data.sourceCode,
- filename: data.filename
- }
- );
- }
- } catch (e) {
- callback(e);
- }
-};
diff --git a/packager/react-packager/src/JSTransformer/worker/__tests__/constant-folding-test.js b/packager/react-packager/src/JSTransformer/worker/__tests__/constant-folding-test.js
index a39a1e970..64ad751fe 100644
--- a/packager/react-packager/src/JSTransformer/worker/__tests__/constant-folding-test.js
+++ b/packager/react-packager/src/JSTransformer/worker/__tests__/constant-folding-test.js
@@ -16,6 +16,16 @@ function parse(code) {
return babel.transform(code, {code: false, babelrc: false, compact: true});
}
+const babelOptions = {
+ babelrc: false,
+ compact: true,
+ retainLines: false,
+};
+
+function normalize({code}) {
+ return babel.transform(code, babelOptions).code;
+}
+
describe('constant expressions', () => {
it('can optimize conditional expressions with constant conditions', () => {
const code = `
@@ -29,7 +39,7 @@ describe('constant expressions', () => {
'foo'==='bar' ? b : c,
f() ? g() : h()
);`;
- expect(constantFolding('arbitrary.js', parse(code)).code)
+ expect(normalize(constantFolding('arbitrary.js', parse(code))))
.toEqual(`a(true,true,2,true,{},{a:1},c,f()?g():h());`);
});
@@ -39,7 +49,7 @@ describe('constant expressions', () => {
var b = 'android' == 'android'
? ('production' != 'production' ? 'a' : 'A')
: 'i';`;
- expect(constantFolding('arbitrary.js', parse(code)).code)
+ expect(normalize(constantFolding('arbitrary.js', parse(code))))
.toEqual(`var a=1;var b='A';`);
});
@@ -48,7 +58,7 @@ describe('constant expressions', () => {
var a = true || 1;
var b = 'android' == 'android' &&
'production' != 'production' || null || "A";`;
- expect(constantFolding('arbitrary.js', parse(code)).code)
+ expect(normalize(constantFolding('arbitrary.js', parse(code))))
.toEqual(`var a=true;var b="A";`);
});
@@ -60,7 +70,7 @@ describe('constant expressions', () => {
var d = null || z();
var e = !1 && z();
`;
- expect(constantFolding('arbitrary.js', parse(code)).code)
+ expect(normalize(constantFolding('arbitrary.js', parse(code))))
.toEqual(`var a="truthy";var b=z();var c=null;var d=z();var e=false;`);
});
@@ -70,7 +80,7 @@ describe('constant expressions', () => {
var a = 1;
}
`;
- expect(constantFolding('arbitrary.js', parse(code)).code)
+ expect(normalize(constantFolding('arbitrary.js', parse(code))))
.toEqual(``);
});
@@ -86,7 +96,7 @@ describe('constant expressions', () => {
var a = 'b';
}
`;
- expect(constantFolding('arbitrary.js', parse(code)).code)
+ expect(normalize(constantFolding('arbitrary.js', parse(code))))
.toEqual(`{var a=3;var b=a+4;}`);
});
@@ -106,7 +116,7 @@ describe('constant expressions', () => {
}
}
`;
- expect(constantFolding('arbitrary.js', parse(code)).code)
+ expect(normalize(constantFolding('arbitrary.js', parse(code))))
.toEqual(`{{require('c');}}`);
});
});
diff --git a/packager/react-packager/src/JSTransformer/worker/__tests__/extract-dependencies-test.js b/packager/react-packager/src/JSTransformer/worker/__tests__/extract-dependencies-test.js
index a27def1dc..fba330eec 100644
--- a/packager/react-packager/src/JSTransformer/worker/__tests__/extract-dependencies-test.js
+++ b/packager/react-packager/src/JSTransformer/worker/__tests__/extract-dependencies-test.js
@@ -22,7 +22,7 @@ describe('Dependency extraction:', () => {
}
});
require
- ('more');`
+ ('more');`;
const {dependencies, dependencyOffsets} = extractDependencies(code);
expect(dependencies)
.toEqual(['foo/bar', 'React', 'Component', 'more']);
@@ -34,11 +34,11 @@ describe('Dependency extraction:', () => {
require('a');
foo.require('b');
bar.
- require ( 'c').require('d')require('e')`;
+ require ( 'c').require('d');require('e')`;
const {dependencies, dependencyOffsets} = extractDependencies(code);
expect(dependencies).toEqual(['a', 'e']);
- expect(dependencyOffsets).toEqual([15, 97]);
+ expect(dependencyOffsets).toEqual([15, 98]);
});
it('does not extract require calls from strings', () => {
@@ -51,7 +51,7 @@ describe('Dependency extraction:', () => {
return require ( "Component" );
}
});
- " \\" require('more')";`
+ " \\" require('more')";`;
const {dependencies, dependencyOffsets} = extractDependencies(code);
expect(dependencies).toEqual(['foo', 'Component']);
@@ -85,12 +85,28 @@ describe('Dependency extraction:', () => {
expect(dependencyOffsets).toEqual([]);
});
+ it('does not extract calls to require with non-static arguments', () => {
+ const code = `require('foo/' + bar)`;
+
+ const {dependencies, dependencyOffsets} = extractDependencies(code);
+ expect(dependencies).toEqual([]);
+ expect(dependencyOffsets).toEqual([]);
+ });
+
it('does not get confused by previous states', () => {
// yes, this was a bug
- const code = `require("a");/* a comment */ var a = /[a]/.test('a');`
+ const code = `require("a");/* a comment */ var a = /[a]/.test('a');`;
const {dependencies, dependencyOffsets} = extractDependencies(code);
expect(dependencies).toEqual(['a']);
expect(dependencyOffsets).toEqual([8]);
});
+
+ it('can handle regular expressions', () => {
+ const code = `require('a'); /["']/.test('foo'); require("b");`;
+
+ const {dependencies, dependencyOffsets} = extractDependencies(code);
+ expect(dependencies).toEqual(['a', 'b']);
+ expect(dependencyOffsets).toEqual([8, 42]);
+ });
});
diff --git a/packager/react-packager/src/JSTransformer/worker/__tests__/minify-test.js b/packager/react-packager/src/JSTransformer/worker/__tests__/minify-test.js
index e65594e7c..78450879e 100644
--- a/packager/react-packager/src/JSTransformer/worker/__tests__/minify-test.js
+++ b/packager/react-packager/src/JSTransformer/worker/__tests__/minify-test.js
@@ -21,91 +21,37 @@ const uglify = {
jest.setMock('uglify-js', uglify);
const minify = require('../minify');
-const {any} = jasmine;
+const {objectContaining} = jasmine;
describe('Minification:', () => {
- const fileName = '/arbitrary/file.js';
- const DEPENDENCY_MARKER = '\u0002\ueffe\ue277\uead5';
+ const filename = '/arbitrary/file.js';
+ const code = 'arbitrary(code)';
let map;
beforeEach(() => {
uglify.minify.mockClear();
- map = {version: 3, sources: [fileName], mappings: ''};
+ uglify.minify.mockReturnValue({code: '', map: '{}'});
+ map = {version: 3, sources: ['?'], mappings: ''};
});
- it('passes the transformed code to `uglify.minify`, wrapped in an immediately invoked function expression', () => {
- const code = 'arbitrary(code)';
- minify('', code, {}, [], []);
- expect(uglify.minify).toBeCalledWith(
- `(function(){${code}}());`, any(Object));
- });
-
- it('uses the passed module locals as parameters of the IIFE', () => {
- const moduleLocals = ['arbitrary', 'parameters'];
- minify('', '', {}, [], moduleLocals);
- expect(uglify.minify).toBeCalledWith(
- `(function(${moduleLocals}){}());`, any(Object));
- });
-
- it('passes the transformed source map to `uglify.minify`', () => {
- minify('', '', map, [], []);
- const [, options] = uglify.minify.mock.calls[0];
- expect(options.inSourceMap).toEqual(map);
- });
-
- it('passes the file name as `outSourceMap` to `uglify.minify` (uglify uses it for the `file` field on the source map)', () => {
- minify(fileName, '', {}, [], []);
- const [, options] = uglify.minify.mock.calls[0];
- expect(options.outSourceMap).toEqual(fileName);
- });
-
- it('inserts a marker for every dependency offset before minifing', () => {
- const code = `
- var React = require('React');
- var Immutable = require('Immutable');`;
- const dependencyOffsets = [27, 67];
- const expectedCode =
- code.replace(/require\('/g, '$&' + DEPENDENCY_MARKER);
-
- minify('', code, {}, dependencyOffsets, []);
- expect(uglify.minify).toBeCalledWith(
- `(function(){${expectedCode}}());`, any(Object));
+ it('passes file name, code, and source map to `uglify`', () => {
+ minify(filename, code, map);
+ expect(uglify.minify).toBeCalledWith(code, objectContaining({
+ fromString: true,
+ inSourceMap: map,
+ outSourceMap: filename,
+ }));
});
it('returns the code provided by uglify', () => {
- const code = 'some(source) + code';
- uglify.minify.mockReturnValue({code: `!function(a,b,c){${code}}()`});
-
- const result = minify('', '', {}, [], []);
+ uglify.minify.mockReturnValue({code, map: '{}'});
+ const result = minify('', '', {});
expect(result.code).toBe(code);
});
- it('extracts dependency offsets from the code provided by uglify', () => {
- const code = `
- var a=r("${DEPENDENCY_MARKER}a-dependency");
- var b=r("\\x02\\ueffe\\ue277\\uead5b-dependency");
- var e=r(a()?'\\u0002\\ueffe\\ue277\\uead5c-dependency'
- :'\x02\ueffe\ue277\uead5d-dependency');`;
- uglify.minify.mockReturnValue({code: `!function(){${code}}());`});
-
- const result = minify('', '', {}, [], []);
- expect(result.dependencyOffsets).toEqual([15, 46, 81, 114]);
- });
-
- it('returns the source map object provided by uglify', () => {
- uglify.minify.mockReturnValue({map, code: ''});
- const result = minify('', '', {}, [], []);
- expect(result.map).toBe(map);
- });
-
- it('adds a `moduleLocals` object to the result that reflects the names of the minified module locals', () => {
- const moduleLocals = ['arbitrary', 'parameters', 'here'];
- uglify.minify.mockReturnValue({code: '(function(a,ll,d){}());'});
- const result = minify('', '', {}, [], moduleLocals);
- expect(result.moduleLocals).toEqual({
- arbitrary: 'a',
- parameters: 'll',
- here: 'd',
- });
+ it('parses the source map object provided by uglify and sets the sources property', () => {
+ uglify.minify.mockReturnValue({map: JSON.stringify(map), code: ''});
+ const result = minify(filename, '', {});
+ expect(result.map).toEqual({...map, sources: [filename]});
});
});
diff --git a/packager/react-packager/src/JSTransformer/worker/__tests__/worker-test.js b/packager/react-packager/src/JSTransformer/worker/__tests__/worker-test.js
index a6acb6689..b08035098 100644
--- a/packager/react-packager/src/JSTransformer/worker/__tests__/worker-test.js
+++ b/packager/react-packager/src/JSTransformer/worker/__tests__/worker-test.js
@@ -78,33 +78,6 @@ describe('code transformation worker:', () => {
});
});
- it('puts an empty `moduleLocals` object on the result', done => {
- transform.mockImplementation(
- (_, callback) => callback(null, {code: 'arbitrary'}));
- transformCode(transform, 'filename', 'code', {}, (_, data) => {
- expect(data.moduleLocals).toEqual({});
- done();
- });
- });
-
- it('if a `moduleLocals` array is passed, the `moduleLocals` object is a key mirror of its items', done => {
- transform.mockImplementation(
- (_, callback) => callback(null, {code: 'arbitrary'}));
- const moduleLocals =
- ['arbitrary', 'list', 'containing', 'variable', 'names'];
-
- transformCode(transform, 'filename', 'code', {moduleLocals}, (_, data) => {
- expect(data.moduleLocals).toEqual({
- arbitrary: 'arbitrary',
- list: 'list',
- containing: 'containing',
- variable: 'variable',
- names: 'names',
- });
- done();
- });
- });
-
describe('dependency extraction:', () => {
let code;
@@ -155,21 +128,19 @@ describe('code transformation worker:', () => {
});
describe('Minifications:', () => {
- let constantFolding, extractDependencies, inline, minify, options;
- let transformResult, dependencyData, moduleLocals;
+ let constantFolding, inline, options;
+ let transformResult, dependencyData;
const filename = 'arbitrary/file.js';
- const foldedCode = 'arbitrary(folded(code));'
- const foldedMap = {version: 3, sources: ['fold.js']}
+ const foldedCode = 'arbitrary(folded(code));';
+ const foldedMap = {version: 3, sources: ['fold.js']};
beforeEach(() => {
constantFolding = require('../constant-folding')
.mockReturnValue({code: foldedCode, map: foldedMap});
extractDependencies = require('../extract-dependencies');
inline = require('../inline');
- minify = require('../minify').mockReturnValue({});
- moduleLocals = ['module', 'require', 'exports'];
- options = {moduleLocals, minify: true};
+ options = {minify: true};
dependencyData = {
dependencies: ['a', 'b', 'c'],
dependencyOffsets: [100, 120, 140]
@@ -206,19 +177,6 @@ describe('code transformation worker:', () => {
});
});
- it('passes the code obtained from `constant-folding` to `minify`', done => {
- transformCode(transform, filename, 'code', options, () => {
- expect(minify).toBeCalledWith(
- filename,
- foldedCode,
- foldedMap,
- dependencyData.dependencyOffsets,
- moduleLocals
- );
- done();
- });
- });
-
it('uses the dependencies obtained from the optimized result', done => {
transformCode(transform, filename, 'code', options, (_, result) => {
expect(result.dependencies).toEqual(dependencyData.dependencies);
@@ -226,17 +184,10 @@ describe('code transformation worker:', () => {
});
});
- it('uses data produced by `minify` for the result', done => {
- const minifyResult = {
- code: 'minified(code)',
- dependencyOffsets: [10, 30, 60],
- map: {version: 3, sources: ['minified.js']},
- moduleLocals: {module: 'x', require: 'y', exports: 'z'},
- };
- minify.mockReturnValue(minifyResult);
-
+ it('uses data produced by `constant-folding` for the result', done => {
transformCode(transform, 'filename', 'code', options, (_, result) => {
- expect(result).toEqual(objectContaining(minifyResult))
+ expect(result)
+ .toEqual(objectContaining({code: foldedCode, map: foldedMap}));
done();
});
});
diff --git a/packager/react-packager/src/JSTransformer/worker/constant-folding.js b/packager/react-packager/src/JSTransformer/worker/constant-folding.js
index acf14f687..f896430f4 100644
--- a/packager/react-packager/src/JSTransformer/worker/constant-folding.js
+++ b/packager/react-packager/src/JSTransformer/worker/constant-folding.js
@@ -73,9 +73,12 @@ function constantFolding(filename, transformResult) {
filename,
plugins: [plugin],
inputSourceMap: transformResult.map,
+ sourceMaps: true,
+ sourceFileName: filename,
babelrc: false,
compact: true,
- })
+ retainLines: true,
+ });
}
module.exports = constantFolding;
diff --git a/packager/react-packager/src/JSTransformer/worker/extract-dependencies.js b/packager/react-packager/src/JSTransformer/worker/extract-dependencies.js
index 3ca221641..4e1bfb396 100644
--- a/packager/react-packager/src/JSTransformer/worker/extract-dependencies.js
+++ b/packager/react-packager/src/JSTransformer/worker/extract-dependencies.js
@@ -8,48 +8,8 @@
*/
'use strict';
-const SINGLE_QUOTE = "'".charCodeAt(0);
-const DOUBLE_QUOTE = '"'.charCodeAt(0);
-const BACKSLASH = '\\'.charCodeAt(0);
-const SLASH = '/'.charCodeAt(0);
-const NEWLINE = '\n'.charCodeAt(0);
-const ASTERISK = '*'.charCodeAt(0);
-
-// dollar is the only regex special character valid in identifiers
-const escapeRegExp = identifier => identifier.replace(/[$]/g, '\\$');
-
-function binarySearch(indexes, index) {
- var low = 0;
- var high = indexes.length - 1;
- var i = 0;
-
- if (indexes[low] === index) {
- return low;
- }
- while (high - low > 1) {
- var current = low + ((high - low) >>> 1); // right shift divides by 2 and floors
- if (index === indexes[current]) {
- return current;
- }
- if (index > indexes[current]) {
- low = current;
- } else {
- high = current;
- }
- }
- return low;
-}
-
-function indexOfCharCode(string, needle, i) {
- for (var charCode; (charCode = string.charCodeAt(i)); i++) {
- if (charCode === needle) {
- return i;
- }
- }
- return -1;
-}
-
-const reRequire = /(?:^|[^.\s])\s*\brequire\s*\(\s*(['"])(.*?)\1/g;
+const babel = require('babel-core');
+const babylon = require('babylon');
/**
* Extracts dependencies (module IDs imported with the `require` function) from
@@ -66,61 +26,24 @@ const reRequire = /(?:^|[^.\s])\s*\brequire\s*\(\s*(['"])(.*?)\1/g;
* The index points to the opening quote.
*/
function extractDependencies(code) {
- const ranges = [0];
- // are we currently in a quoted string? -> SINGLE_QUOTE or DOUBLE_QUOTE, else undefined
- var currentQuote;
- // scan the code for string literals and comments.
- for (var i = 0, charCode; (charCode = code.charCodeAt(i)); i++) {
- if (charCode === BACKSLASH) {
- i += 1;
- continue;
- }
-
- if (charCode === SLASH && currentQuote === undefined) {
- var next = code.charCodeAt(i + 1);
- var end = undefined;
- if (next === SLASH) {
- end = indexOfCharCode(code, NEWLINE, i + 2);
- } else if (next === ASTERISK) {
- end = code.indexOf('*/', i + 2) + 1; // assume valid JS input here
- }
- if (end === -1) {
- // if the comment does not end, it goes to the end of the file
- end += code.length;
- }
- if (end !== undefined) {
- ranges.push(i, end);
- i = end;
- continue;
- }
- }
-
- var isQuoteStart = currentQuote === undefined &&
- (charCode === SINGLE_QUOTE || charCode === DOUBLE_QUOTE);
- if (isQuoteStart || currentQuote === charCode) {
- ranges.push(i);
- currentQuote = currentQuote === charCode ? undefined : charCode;
- }
- }
- ranges.push(i);
-
- // extract dependencies
+ const ast = babylon.parse(code);
const dependencies = new Set();
const dependencyOffsets = [];
- for (var match; (match = reRequire.exec(code)); ) {
- // check whether the match is in a code range, and not inside of a string
- // literal or a comment
- if (binarySearch(ranges, match.index) % 2 === 0) {
- dependencies.add(match[2]);
- dependencyOffsets.push(
- match[0].length - match[2].length - 2 + match.index);
- }
- }
- return {
- dependencyOffsets,
- dependencies: Array.from(dependencies.values()),
- };
+ babel.traverse(ast, {
+ CallExpression(path) {
+ const node = path.node;
+ const callee = node.callee;
+ const arg = node.arguments[0];
+ if (callee.type !== 'Identifier' || callee.name !== 'require' || !arg || arg.type !== 'StringLiteral') {
+ return;
+ }
+ dependencyOffsets.push(arg.start);
+ dependencies.add(arg.value);
+ }
+ });
+
+ return {dependencyOffsets, dependencies: Array.from(dependencies)};
}
module.exports = extractDependencies;
diff --git a/packager/react-packager/src/JSTransformer/worker/index.js b/packager/react-packager/src/JSTransformer/worker/index.js
index bc6e93338..1b68feaed 100644
--- a/packager/react-packager/src/JSTransformer/worker/index.js
+++ b/packager/react-packager/src/JSTransformer/worker/index.js
@@ -13,12 +13,6 @@ const extractDependencies = require('./extract-dependencies');
const inline = require('./inline');
const minify = require('./minify');
-function keyMirrorFromArray(array) {
- var keyMirror = {};
- array.forEach(key => keyMirror[key] = key);
- return keyMirror;
-}
-
function makeTransformParams(filename, sourceCode, options) {
if (filename.endsWith('.json')) {
sourceCode = 'module.exports=' + sourceCode;
@@ -28,7 +22,6 @@ function makeTransformParams(filename, sourceCode, options) {
function transformCode(transform, filename, sourceCode, options, callback) {
const params = makeTransformParams(filename, sourceCode, options.transform);
- const moduleLocals = options.moduleLocals || [];
const isJson = filename.endsWith('.json');
transform(params, (error, transformed) => {
@@ -52,28 +45,35 @@ function transformCode(transform, filename, sourceCode, options, callback) {
code = code.replace(/^\w+\.exports=/, '');
}
- const moduleLocals = options.moduleLocals || [];
- const dependencyData = isJson || options.extern
+ const result = isJson || options.extern
? {dependencies: [], dependencyOffsets: []}
: extractDependencies(code);
- var result;
- if (options.minify) {
- result = minify(
- filename, code, map, dependencyData.dependencyOffsets, moduleLocals);
- result.dependencies = dependencyData.dependencies;
- } else {
- result = dependencyData;
- result.code = code;
- result.map = map;
- result.moduleLocals = keyMirrorFromArray(moduleLocals);
- }
+ result.code = code;
+ result.map = map;
callback(null, result);
});
}
-module.exports = function(transform, filename, sourceCode, options, callback) {
+exports.transformAndExtractDependencies = (
+ transform,
+ filename,
+ sourceCode,
+ options,
+ callback
+) => {
transformCode(require(transform), filename, sourceCode, options || {}, callback);
};
-module.exports.transformCode = transformCode; // for easier testing
+
+exports.minify = (filename, code, sourceMap, callback) => {
+ var result;
+ try {
+ result = minify(filename, code, sourceMap);
+ } catch (error) {
+ callback(error);
+ }
+ callback(null, result);
+};
+
+exports.transformCode = transformCode; // for easier testing
diff --git a/packager/react-packager/src/JSTransformer/worker/inline.js b/packager/react-packager/src/JSTransformer/worker/inline.js
index 2a419933a..a294bcefc 100644
--- a/packager/react-packager/src/JSTransformer/worker/inline.js
+++ b/packager/react-packager/src/JSTransformer/worker/inline.js
@@ -89,6 +89,8 @@ function inline(filename, transformResult, options) {
filename,
plugins: [[plugin, options]],
inputSourceMap: transformResult.map,
+ sourceMaps: true,
+ sourceFileName: filename,
code: false,
babelrc: false,
compact: true,
diff --git a/packager/react-packager/src/JSTransformer/worker/minify.js b/packager/react-packager/src/JSTransformer/worker/minify.js
index d34359187..089cfc787 100644
--- a/packager/react-packager/src/JSTransformer/worker/minify.js
+++ b/packager/react-packager/src/JSTransformer/worker/minify.js
@@ -10,63 +10,10 @@
const uglify = require('uglify-js');
-const MAGIC_MARKER = '\u0002\ueffe\ue277\uead5';
-const MAGIC_MARKER_SPLITTER =
- /(?:\x02|\\u0002|\\x02)(?:\ueffe|\\ueffe)(?:\ue277|\\ue277)(?:\uead5|\\uead5)/;
-
-// IIFE = "immediately invoked function expression"
-// we wrap modules in functions to allow the minifier to mangle local variables
-function wrapCodeInIIFE(code, moduleLocals) {
- return `(function(${moduleLocals.join(',')}){${code}}());`;
-}
-
-function extractCodeFromIIFE(code) {
- return code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'));
-}
-
-function extractModuleLocalsFromIIFE(code) {
- return code.substring(code.indexOf('(', 1) + 1, code.indexOf(')')).split(',');
-}
-
-function splitFirstElementAt(array, offset) {
- const first = array.shift();
- array.unshift(first.slice(0, offset + 1), first.slice(offset + 1));
- return array;
-}
-
-function insertMarkers(code, dependencyOffsets) {
- return dependencyOffsets
- .reduceRight(splitFirstElementAt, [code])
- .join(MAGIC_MARKER);
-}
-
-function extractMarkers(codeWithMarkers) {
- const dependencyOffsets = [];
- const codeBits = codeWithMarkers.split(MAGIC_MARKER_SPLITTER);
- var offset = 0;
- for (var i = 0, max = codeBits.length - 1; i < max; i++) {
- offset += codeBits[i].length;
- dependencyOffsets.push(offset - 1);
- }
-
- return {code: codeBits.join(''), dependencyOffsets};
-}
-
-function minify(filename, code, map, dependencyOffsets, moduleLocals) {
- // before minifying, code is wrapped in an immediately invoked function
- // expression, so that top level variables can be shortened safely
- code = wrapCodeInIIFE(
- // since we don't know where the strings specifying dependencies will be
- // located in the minified code, we mark them with a special marker string
- // and extract them afterwards.
- // That way, post-processing code can use these positions
- insertMarkers(code, dependencyOffsets),
- moduleLocals
- );
-
+function minify(filename, code, sourceMap) {
const minifyResult = uglify.minify(code, {
fromString: true,
- inSourceMap: map,
+ inSourceMap: sourceMap,
outSourceMap: filename,
output: {
ascii_only: true,
@@ -74,15 +21,9 @@ function minify(filename, code, map, dependencyOffsets, moduleLocals) {
},
});
- const minifiedModuleLocals = extractModuleLocalsFromIIFE(minifyResult.code);
- const codeWithMarkers = extractCodeFromIIFE(minifyResult.code);
- const result = extractMarkers(codeWithMarkers);
- result.map = minifyResult.map;
- result.moduleLocals = {};
- moduleLocals.forEach(
- (key, i) => result.moduleLocals[key] = minifiedModuleLocals[i]);
-
- return result;
+ minifyResult.map = JSON.parse(minifyResult.map);
+ minifyResult.map.sources = [filename];
+ return minifyResult;
}
module.exports = minify;
diff --git a/packager/react-packager/src/Resolver/__tests__/Resolver-test.js b/packager/react-packager/src/Resolver/__tests__/Resolver-test.js
index b12ebd48d..df6f609e8 100644
--- a/packager/react-packager/src/Resolver/__tests__/Resolver-test.js
+++ b/packager/react-packager/src/Resolver/__tests__/Resolver-test.js
@@ -31,6 +31,7 @@ describe('Resolver', function() {
this.getName = jest.genMockFn();
this.getDependencies = jest.genMockFn();
this.isPolyfill = jest.genMockFn().mockReturnValue(false);
+ this.isJSON = jest.genMockFn().mockReturnValue(false);
});
Polyfill = jest.genMockFn().mockImpl(function() {
var polyfill = new Module();
@@ -61,6 +62,10 @@ describe('Resolver', function() {
finalize() {
return Promise.resolve(this);
}
+
+ getResolvedDependencyPairs() {
+ return [];
+ }
}
function createModule(id, dependencies) {
@@ -70,6 +75,12 @@ describe('Resolver', function() {
return module;
}
+ function createJsonModule(id) {
+ const module = createModule(id, []);
+ module.isJSON.mockReturnValue(true);
+ return module;
+ }
+
function createPolyfill(id, dependencies) {
var polyfill = new Polyfill({});
polyfill.getName = jest.genMockFn().mockImpl(() => Promise.resolve(id));
@@ -79,6 +90,23 @@ describe('Resolver', function() {
}
describe('getDependencies', function() {
+ it('forwards transform options to the dependency graph', function() {
+ const transformOptions = {arbitrary: 'options'};
+ const platform = 'ios';
+ const entry = '/root/index.js';
+
+ DependencyGraph.prototype.getDependencies.mockImplementation(
+ () => Promise.reject());
+ new Resolver({projectRoot: '/root', })
+ .getDependencies(entry, {platform}, transformOptions);
+ expect(DependencyGraph.prototype.getDependencies).toBeCalledWith({
+ entryPath: entry,
+ platform: platform,
+ transformOptions: transformOptions,
+ recursive: true,
+ });
+ });
+
pit('should get dependencies with polyfills', function() {
var module = createModule('index');
var deps = [module];
@@ -242,388 +270,8 @@ describe('Resolver', function() {
projectRoot: '/root',
});
- var dependencies = ['x', 'y', 'z', 'a', 'b'];
-
/*eslint-disable */
var code = [
- // single line import
- "import'x';",
- "import 'x';",
- "import 'x' ;",
- "import Default from 'x';",
- "import * as All from 'x';",
- "import {} from 'x';",
- "import { } from 'x';",
- "import {Foo} from 'x';",
- "import { Foo } from 'x';",
- "import { Foo, } from 'x';",
- "import {Foo as Bar} from 'x';",
- "import { Foo as Bar } from 'x';",
- "import { Foo as Bar, } from 'x';",
- "import { Foo, Bar } from 'x';",
- "import { Foo, Bar, } from 'x';",
- "import { Foo as Bar, Baz } from 'x';",
- "import { Foo as Bar, Baz, } from 'x';",
- "import { Foo, Bar as Baz } from 'x';",
- "import { Foo, Bar as Baz, } from 'x';",
- "import { Foo as Bar, Baz as Qux } from 'x';",
- "import { Foo as Bar, Baz as Qux, } from 'x';",
- "import { Foo, Bar, Baz } from 'x';",
- "import { Foo, Bar, Baz, } from 'x';",
- "import { Foo as Bar, Baz, Qux } from 'x';",
- "import { Foo as Bar, Baz, Qux, } from 'x';",
- "import { Foo, Bar as Baz, Qux } from 'x';",
- "import { Foo, Bar as Baz, Qux, } from 'x';",
- "import { Foo, Bar, Baz as Qux } from 'x';",
- "import { Foo, Bar, Baz as Qux, } from 'x';",
- "import { Foo as Bar, Baz as Qux, Norf } from 'x';",
- "import { Foo as Bar, Baz as Qux, Norf, } from 'x';",
- "import { Foo as Bar, Baz, Qux as Norf } from 'x';",
- "import { Foo as Bar, Baz, Qux as Norf, } from 'x';",
- "import { Foo, Bar as Baz, Qux as Norf } from 'x';",
- "import { Foo, Bar as Baz, Qux as Norf, } from 'x';",
- "import { Foo as Bar, Baz as Qux, Norf as Enuf } from 'x';",
- "import { Foo as Bar, Baz as Qux, Norf as Enuf, } from 'x';",
- "import Default, * as All from 'x';",
- "import Default, { } from 'x';",
- "import Default, { Foo } from 'x';",
- "import Default, { Foo, } from 'x';",
- "import Default, { Foo as Bar } from 'x';",
- "import Default, { Foo as Bar, } from 'x';",
- "import Default, { Foo, Bar } from 'x';",
- "import Default, { Foo, Bar, } from 'x';",
- "import Default, { Foo as Bar, Baz } from 'x';",
- "import Default, { Foo as Bar, Baz, } from 'x';",
- "import Default, { Foo, Bar as Baz } from 'x';",
- "import Default, { Foo, Bar as Baz, } from 'x';",
- "import Default, { Foo as Bar, Baz as Qux } from 'x';",
- "import Default, { Foo as Bar, Baz as Qux, } from 'x';",
- "import Default, { Foo, Bar, Baz } from 'x';",
- "import Default, { Foo, Bar, Baz, } from 'x';",
- "import Default, { Foo as Bar, Baz, Qux } from 'x';",
- "import Default, { Foo as Bar, Baz, Qux, } from 'x';",
- "import Default, { Foo, Bar as Baz, Qux } from 'x';",
- "import Default, { Foo, Bar as Baz, Qux, } from 'x';",
- "import Default, { Foo, Bar, Baz as Qux } from 'x';",
- "import Default, { Foo, Bar, Baz as Qux, } from 'x';",
- "import Default, { Foo as Bar, Baz as Qux, Norf } from 'x';",
- "import Default, { Foo as Bar, Baz as Qux, Norf, } from 'x';",
- "import Default, { Foo as Bar, Baz, Qux as Norf } from 'x';",
- "import Default, { Foo as Bar, Baz, Qux as Norf, } from 'x';",
- "import Default, { Foo, Bar as Baz, Qux as Norf } from 'x';",
- "import Default, { Foo, Bar as Baz, Qux as Norf, } from 'x';",
- "import Default, { Foo as Bar, Baz as Qux, Norf as NoMore } from 'x';",
- "import Default, { Foo as Bar, Baz as Qux, Norf as NoMore, } from 'x';",
- "import Default , { } from 'x';",
- 'import "x";',
- 'import Default from "x";',
- 'import * as All from "x";',
- 'import { } from "x";',
- 'import { Foo } from "x";',
- 'import { Foo, } from "x";',
- 'import { Foo as Bar } from "x";',
- 'import { Foo as Bar, } from "x";',
- 'import { Foo, Bar } from "x";',
- 'import { Foo, Bar, } from "x";',
- 'import { Foo as Bar, Baz } from "x";',
- 'import { Foo as Bar, Baz, } from "x";',
- 'import { Foo, Bar as Baz } from "x";',
- 'import { Foo, Bar as Baz, } from "x";',
- 'import { Foo as Bar, Baz as Qux } from "x";',
- 'import { Foo as Bar, Baz as Qux, } from "x";',
- 'import { Foo, Bar, Baz } from "x";',
- 'import { Foo, Bar, Baz, } from "x";',
- 'import { Foo as Bar, Baz, Qux } from "x";',
- 'import { Foo as Bar, Baz, Qux, } from "x";',
- 'import { Foo, Bar as Baz, Qux } from "x";',
- 'import { Foo, Bar as Baz, Qux, } from "x";',
- 'import { Foo, Bar, Baz as Qux } from "x";',
- 'import { Foo, Bar, Baz as Qux, } from "x";',
- 'import { Foo as Bar, Baz as Qux, Norf } from "x";',
- 'import { Foo as Bar, Baz as Qux, Norf, } from "x";',
- 'import { Foo as Bar, Baz, Qux as Norf } from "x";',
- 'import { Foo as Bar, Baz, Qux as Norf, } from "x";',
- 'import { Foo, Bar as Baz, Qux as Norf } from "x";',
- 'import { Foo, Bar as Baz, Qux as Norf, } from "x";',
- 'import { Foo as Bar, Baz as Qux, Norf as NoMore } from "x";',
- 'import { Foo as Bar, Baz as Qux, Norf as NoMore, } from "x";',
- 'import Default, * as All from "x";',
- 'import Default, { } from "x";',
- 'import Default, { Foo } from "x";',
- 'import Default, { Foo, } from "x";',
- 'import Default, { Foo as Bar } from "x";',
- 'import Default, { Foo as Bar, } from "x";',
- 'import Default, { Foo, Bar } from "x";',
- 'import Default, { Foo, Bar, } from "x";',
- 'import Default, { Foo as Bar, Baz } from "x";',
- 'import Default, { Foo as Bar, Baz, } from "x";',
- 'import Default, { Foo, Bar as Baz } from "x";',
- 'import Default, { Foo, Bar as Baz, } from "x";',
- 'import Default, { Foo as Bar, Baz as Qux } from "x";',
- 'import Default, { Foo as Bar, Baz as Qux, } from "x";',
- 'import Default, { Foo, Bar, Baz } from "x";',
- 'import Default, { Foo, Bar, Baz, } from "x";',
- 'import Default, { Foo as Bar, Baz, Qux } from "x";',
- 'import Default, { Foo as Bar, Baz, Qux, } from "x";',
- 'import Default, { Foo, Bar as Baz, Qux } from "x";',
- 'import Default, { Foo, Bar as Baz, Qux, } from "x";',
- 'import Default, { Foo, Bar, Baz as Qux } from "x";',
- 'import Default, { Foo, Bar, Baz as Qux, } from "x";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf } from "x";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf, } from "x";',
- 'import Default, { Foo as Bar, Baz, Qux as Norf } from "x";',
- 'import Default, { Foo as Bar, Baz, Qux as Norf, } from "x";',
- 'import Default, { Foo, Bar as Baz, Qux as Norf } from "x";',
- 'import Default, { Foo, Bar as Baz, Qux as Norf, } from "x";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf } from "x";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf, } from "x";',
- 'import Default from "y";',
- 'import * as All from \'z\';',
- // import with support for new lines
- "import { Foo,\n Bar }\n from 'x';",
- "import { \nFoo,\nBar,\n }\n from 'x';",
- "import { Foo as Bar,\n Baz\n }\n from 'x';",
- "import { \nFoo as Bar,\n Baz\n, }\n from 'x';",
- "import { Foo,\n Bar as Baz\n }\n from 'x';",
- "import { Foo,\n Bar as Baz,\n }\n from 'x';",
- "import { Foo as Bar,\n Baz as Qux\n }\n from 'x';",
- "import { Foo as Bar,\n Baz as Qux,\n }\n from 'x';",
- "import { Foo,\n Bar,\n Baz }\n from 'x';",
- "import { Foo,\n Bar,\n Baz,\n }\n from 'x';",
- "import { Foo as Bar,\n Baz,\n Qux\n }\n from 'x';",
- "import { Foo as Bar,\n Baz,\n Qux,\n }\n from 'x';",
- "import { Foo,\n Bar as Baz,\n Qux\n }\n from 'x';",
- "import { Foo,\n Bar as Baz,\n Qux,\n }\n from 'x';",
- "import { Foo,\n Bar,\n Baz as Qux\n }\n from 'x';",
- "import { Foo,\n Bar,\n Baz as Qux,\n }\n from 'x';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'x';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'x';",
- "import { Foo as Bar,\n Baz,\n Qux as Norf\n }\n from 'x';",
- "import { Foo as Bar,\n Baz,\n Qux as Norf,\n }\n from 'x';",
- "import { Foo,\n Bar as Baz,\n Qux as Norf\n }\n from 'x';",
- "import { Foo,\n Bar as Baz,\n Qux as Norf,\n }\n from 'x';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf as Enuf\n }\n from 'x';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf as Enuf,\n }\n from 'x';",
- "import Default,\n * as All from 'x';",
- "import Default,\n { } from 'x';",
- "import Default,\n { Foo\n }\n from 'x';",
- "import Default,\n { Foo,\n }\n from 'x';",
- "import Default,\n { Foo as Bar\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar\n } from\n 'x';",
- "import Default,\n { Foo,\n Bar,\n } from\n 'x';",
- "import Default,\n { Foo as Bar,\n Baz\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz,\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar as Baz\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar as Baz,\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz as Qux\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar,\n Baz\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar,\n Baz,\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux,\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar as Baz,\n Qux\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar as Baz,\n Qux,\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar,\n Baz as Qux\n }\n from 'x';",
- "import Default,\n { Foo,\n Bar,\n Baz as Qux,\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux as Norf }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux as Norf, }\n from 'x';",
- "import Default,\n { Foo, Bar as Baz,\n Qux as Norf }\n from 'x';",
- "import Default,\n { Foo, Bar as Baz,\n Qux as Norf, }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore\n }\n from 'x';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore,\n }\n from 'x';",
- "import Default\n , { } from 'x';",
- // single line export
- "export'x';",
- "export 'x';",
- "export 'x' ;",
- "export Default from 'x';",
- "export * as All from 'x';",
- "export {} from 'x';",
- "export { } from 'x';",
- "export {Foo} from 'x';",
- "export { Foo } from 'x';",
- "export { Foo, } from 'x';",
- "export {Foo as Bar} from 'x';",
- "export { Foo as Bar } from 'x';",
- "export { Foo as Bar, } from 'x';",
- "export { Foo, Bar } from 'x';",
- "export { Foo, Bar, } from 'x';",
- "export { Foo as Bar, Baz } from 'x';",
- "export { Foo as Bar, Baz, } from 'x';",
- "export { Foo, Bar as Baz } from 'x';",
- "export { Foo, Bar as Baz, } from 'x';",
- "export { Foo as Bar, Baz as Qux } from 'x';",
- "export { Foo as Bar, Baz as Qux, } from 'x';",
- "export { Foo, Bar, Baz } from 'x';",
- "export { Foo, Bar, Baz, } from 'x';",
- "export { Foo as Bar, Baz, Qux } from 'x';",
- "export { Foo as Bar, Baz, Qux, } from 'x';",
- "export { Foo, Bar as Baz, Qux } from 'x';",
- "export { Foo, Bar as Baz, Qux, } from 'x';",
- "export { Foo, Bar, Baz as Qux } from 'x';",
- "export { Foo, Bar, Baz as Qux, } from 'x';",
- "export { Foo as Bar, Baz as Qux, Norf } from 'x';",
- "export { Foo as Bar, Baz as Qux, Norf, } from 'x';",
- "export { Foo as Bar, Baz, Qux as Norf } from 'x';",
- "export { Foo as Bar, Baz, Qux as Norf, } from 'x';",
- "export { Foo, Bar as Baz, Qux as Norf } from 'x';",
- "export { Foo, Bar as Baz, Qux as Norf, } from 'x';",
- "export { Foo as Bar, Baz as Qux, Norf as Enuf } from 'x';",
- "export { Foo as Bar, Baz as Qux, Norf as Enuf, } from 'x';",
- "export Default, * as All from 'x';",
- "export Default, { } from 'x';",
- "export Default, { Foo } from 'x';",
- "export Default, { Foo, } from 'x';",
- "export Default, { Foo as Bar } from 'x';",
- "export Default, { Foo as Bar, } from 'x';",
- "export Default, { Foo, Bar } from 'x';",
- "export Default, { Foo, Bar, } from 'x';",
- "export Default, { Foo as Bar, Baz } from 'x';",
- "export Default, { Foo as Bar, Baz, } from 'x';",
- "export Default, { Foo, Bar as Baz } from 'x';",
- "export Default, { Foo, Bar as Baz, } from 'x';",
- "export Default, { Foo as Bar, Baz as Qux } from 'x';",
- "export Default, { Foo as Bar, Baz as Qux, } from 'x';",
- "export Default, { Foo, Bar, Baz } from 'x';",
- "export Default, { Foo, Bar, Baz, } from 'x';",
- "export Default, { Foo as Bar, Baz, Qux } from 'x';",
- "export Default, { Foo as Bar, Baz, Qux, } from 'x';",
- "export Default, { Foo, Bar as Baz, Qux } from 'x';",
- "export Default, { Foo, Bar as Baz, Qux, } from 'x';",
- "export Default, { Foo, Bar, Baz as Qux } from 'x';",
- "export Default, { Foo, Bar, Baz as Qux, } from 'x';",
- "export Default, { Foo as Bar, Baz as Qux, Norf } from 'x';",
- "export Default, { Foo as Bar, Baz as Qux, Norf, } from 'x';",
- "export Default, { Foo as Bar, Baz, Qux as Norf } from 'x';",
- "export Default, { Foo as Bar, Baz, Qux as Norf, } from 'x';",
- "export Default, { Foo, Bar as Baz, Qux as Norf } from 'x';",
- "export Default, { Foo, Bar as Baz, Qux as Norf, } from 'x';",
- "export Default, { Foo as Bar, Baz as Qux, Norf as NoMore } from 'x';",
- "export Default, { Foo as Bar, Baz as Qux, Norf as NoMore, } from 'x';",
- "export Default , { } from 'x';",
- 'export "x";',
- 'export Default from "x";',
- 'export * as All from "x";',
- 'export { } from "x";',
- 'export { Foo } from "x";',
- 'export { Foo, } from "x";',
- 'export { Foo as Bar } from "x";',
- 'export { Foo as Bar, } from "x";',
- 'export { Foo, Bar } from "x";',
- 'export { Foo, Bar, } from "x";',
- 'export { Foo as Bar, Baz } from "x";',
- 'export { Foo as Bar, Baz, } from "x";',
- 'export { Foo, Bar as Baz } from "x";',
- 'export { Foo, Bar as Baz, } from "x";',
- 'export { Foo as Bar, Baz as Qux } from "x";',
- 'export { Foo as Bar, Baz as Qux, } from "x";',
- 'export { Foo, Bar, Baz } from "x";',
- 'export { Foo, Bar, Baz, } from "x";',
- 'export { Foo as Bar, Baz, Qux } from "x";',
- 'export { Foo as Bar, Baz, Qux, } from "x";',
- 'export { Foo, Bar as Baz, Qux } from "x";',
- 'export { Foo, Bar as Baz, Qux, } from "x";',
- 'export { Foo, Bar, Baz as Qux } from "x";',
- 'export { Foo, Bar, Baz as Qux, } from "x";',
- 'export { Foo as Bar, Baz as Qux, Norf } from "x";',
- 'export { Foo as Bar, Baz as Qux, Norf, } from "x";',
- 'export { Foo as Bar, Baz, Qux as Norf } from "x";',
- 'export { Foo as Bar, Baz, Qux as Norf, } from "x";',
- 'export { Foo, Bar as Baz, Qux as Norf } from "x";',
- 'export { Foo, Bar as Baz, Qux as Norf, } from "x";',
- 'export { Foo as Bar, Baz as Qux, Norf as NoMore } from "x";',
- 'export { Foo as Bar, Baz as Qux, Norf as NoMore, } from "x";',
- 'export Default, * as All from "x";',
- 'export Default, { } from "x";',
- 'export Default, { Foo } from "x";',
- 'export Default, { Foo, } from "x";',
- 'export Default, { Foo as Bar } from "x";',
- 'export Default, { Foo as Bar, } from "x";',
- 'export Default, { Foo, Bar } from "x";',
- 'export Default, { Foo, Bar, } from "x";',
- 'export Default, { Foo as Bar, Baz } from "x";',
- 'export Default, { Foo as Bar, Baz, } from "x";',
- 'export Default, { Foo, Bar as Baz } from "x";',
- 'export Default, { Foo, Bar as Baz, } from "x";',
- 'export Default, { Foo as Bar, Baz as Qux } from "x";',
- 'export Default, { Foo as Bar, Baz as Qux, } from "x";',
- 'export Default, { Foo, Bar, Baz } from "x";',
- 'export Default, { Foo, Bar, Baz, } from "x";',
- 'export Default, { Foo as Bar, Baz, Qux } from "x";',
- 'export Default, { Foo as Bar, Baz, Qux, } from "x";',
- 'export Default, { Foo, Bar as Baz, Qux } from "x";',
- 'export Default, { Foo, Bar as Baz, Qux, } from "x";',
- 'export Default, { Foo, Bar, Baz as Qux } from "x";',
- 'export Default, { Foo, Bar, Baz as Qux, } from "x";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf } from "x";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf, } from "x";',
- 'export Default, { Foo as Bar, Baz, Qux as Norf } from "x";',
- 'export Default, { Foo as Bar, Baz, Qux as Norf, } from "x";',
- 'export Default, { Foo, Bar as Baz, Qux as Norf } from "x";',
- 'export Default, { Foo, Bar as Baz, Qux as Norf, } from "x";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf as Enuf } from "x";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf as Enuf, } from "x";',
- 'export Default from "y";',
- 'export * as All from \'z\';',
- // export with support for new lines
- "export { Foo,\n Bar }\n from 'x';",
- "export { \nFoo,\nBar,\n }\n from 'x';",
- "export { Foo as Bar,\n Baz\n }\n from 'x';",
- "export { \nFoo as Bar,\n Baz\n, }\n from 'x';",
- "export { Foo,\n Bar as Baz\n }\n from 'x';",
- "export { Foo,\n Bar as Baz,\n }\n from 'x';",
- "export { Foo as Bar,\n Baz as Qux\n }\n from 'x';",
- "export { Foo as Bar,\n Baz as Qux,\n }\n from 'x';",
- "export { Foo,\n Bar,\n Baz }\n from 'x';",
- "export { Foo,\n Bar,\n Baz,\n }\n from 'x';",
- "export { Foo as Bar,\n Baz,\n Qux\n }\n from 'x';",
- "export { Foo as Bar,\n Baz,\n Qux,\n }\n from 'x';",
- "export { Foo,\n Bar as Baz,\n Qux\n }\n from 'x';",
- "export { Foo,\n Bar as Baz,\n Qux,\n }\n from 'x';",
- "export { Foo,\n Bar,\n Baz as Qux\n }\n from 'x';",
- "export { Foo,\n Bar,\n Baz as Qux,\n }\n from 'x';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'x';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'x';",
- "export { Foo as Bar,\n Baz,\n Qux as Norf\n }\n from 'x';",
- "export { Foo as Bar,\n Baz,\n Qux as Norf,\n }\n from 'x';",
- "export { Foo,\n Bar as Baz,\n Qux as Norf\n }\n from 'x';",
- "export { Foo,\n Bar as Baz,\n Qux as Norf,\n }\n from 'x';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf as Enuf\n }\n from 'x';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf as Enuf,\n }\n from 'x';",
- "export Default,\n * as All from 'x';",
- "export Default,\n { } from 'x';",
- "export Default,\n { Foo\n }\n from 'x';",
- "export Default,\n { Foo,\n }\n from 'x';",
- "export Default,\n { Foo as Bar\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar\n } from\n 'x';",
- "export Default,\n { Foo,\n Bar,\n } from\n 'x';",
- "export Default,\n { Foo as Bar,\n Baz\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz,\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar as Baz\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar as Baz,\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz as Qux\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar,\n Baz\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar,\n Baz,\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux,\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar as Baz,\n Qux\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar as Baz,\n Qux,\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar,\n Baz as Qux\n }\n from 'x';",
- "export Default,\n { Foo,\n Bar,\n Baz as Qux,\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux as Norf }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux as Norf, }\n from 'x';",
- "export Default,\n { Foo, Bar as Baz,\n Qux as Norf }\n from 'x';",
- "export Default,\n { Foo, Bar as Baz,\n Qux as Norf, }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore\n }\n from 'x';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore,\n }\n from 'x';",
- "export Default\n , { } from 'x';",
// require
'require("x")',
'require("y")',
@@ -633,8 +281,16 @@ describe('Resolver', function() {
].join('\n');
/*eslint-disable */
- const module = createModule('test module', ['x', 'y']);
+ function *findDependencyOffsets() {
+ const re = /(['"']).*?\1/g;
+ let match;
+ while ((match = re.exec(code))) {
+ yield match.index;
+ }
+ }
+ const dependencyOffsets = Array.from(findDependencyOffsets());
+ const module = createModule('test module', ['x', 'y']);
const resolutionResponse = new ResolutionResponseMock({
dependencies: [module],
mainModuleId: 'test module',
@@ -647,393 +303,15 @@ describe('Resolver', function() {
];
}
- return depResolver.wrapModule(
+ return depResolver.wrapModule({
resolutionResponse,
- createModule('test module', ['x', 'y']),
- code
- ).then(processedCode => {
- expect(processedCode.name).toEqual('test module');
- expect(processedCode.code).toEqual([
- '__d(\'test module\',function(global, require,' +
- ' module, exports) { ' +
- // single line import
- "import'x';",
- "import 'changed';",
- "import 'changed' ;",
- "import Default from 'changed';",
- "import * as All from 'changed';",
- "import {} from 'changed';",
- "import { } from 'changed';",
- "import {Foo} from 'changed';",
- "import { Foo } from 'changed';",
- "import { Foo, } from 'changed';",
- "import {Foo as Bar} from 'changed';",
- "import { Foo as Bar } from 'changed';",
- "import { Foo as Bar, } from 'changed';",
- "import { Foo, Bar } from 'changed';",
- "import { Foo, Bar, } from 'changed';",
- "import { Foo as Bar, Baz } from 'changed';",
- "import { Foo as Bar, Baz, } from 'changed';",
- "import { Foo, Bar as Baz } from 'changed';",
- "import { Foo, Bar as Baz, } from 'changed';",
- "import { Foo as Bar, Baz as Qux } from 'changed';",
- "import { Foo as Bar, Baz as Qux, } from 'changed';",
- "import { Foo, Bar, Baz } from 'changed';",
- "import { Foo, Bar, Baz, } from 'changed';",
- "import { Foo as Bar, Baz, Qux } from 'changed';",
- "import { Foo as Bar, Baz, Qux, } from 'changed';",
- "import { Foo, Bar as Baz, Qux } from 'changed';",
- "import { Foo, Bar as Baz, Qux, } from 'changed';",
- "import { Foo, Bar, Baz as Qux } from 'changed';",
- "import { Foo, Bar, Baz as Qux, } from 'changed';",
- "import { Foo as Bar, Baz as Qux, Norf } from 'changed';",
- "import { Foo as Bar, Baz as Qux, Norf, } from 'changed';",
- "import { Foo as Bar, Baz, Qux as Norf } from 'changed';",
- "import { Foo as Bar, Baz, Qux as Norf, } from 'changed';",
- "import { Foo, Bar as Baz, Qux as Norf } from 'changed';",
- "import { Foo, Bar as Baz, Qux as Norf, } from 'changed';",
- "import { Foo as Bar, Baz as Qux, Norf as Enuf } from 'changed';",
- "import { Foo as Bar, Baz as Qux, Norf as Enuf, } from 'changed';",
- "import Default, * as All from 'changed';",
- "import Default, { } from 'changed';",
- "import Default, { Foo } from 'changed';",
- "import Default, { Foo, } from 'changed';",
- "import Default, { Foo as Bar } from 'changed';",
- "import Default, { Foo as Bar, } from 'changed';",
- "import Default, { Foo, Bar } from 'changed';",
- "import Default, { Foo, Bar, } from 'changed';",
- "import Default, { Foo as Bar, Baz } from 'changed';",
- "import Default, { Foo as Bar, Baz, } from 'changed';",
- "import Default, { Foo, Bar as Baz } from 'changed';",
- "import Default, { Foo, Bar as Baz, } from 'changed';",
- "import Default, { Foo as Bar, Baz as Qux } from 'changed';",
- "import Default, { Foo as Bar, Baz as Qux, } from 'changed';",
- "import Default, { Foo, Bar, Baz } from 'changed';",
- "import Default, { Foo, Bar, Baz, } from 'changed';",
- "import Default, { Foo as Bar, Baz, Qux } from 'changed';",
- "import Default, { Foo as Bar, Baz, Qux, } from 'changed';",
- "import Default, { Foo, Bar as Baz, Qux } from 'changed';",
- "import Default, { Foo, Bar as Baz, Qux, } from 'changed';",
- "import Default, { Foo, Bar, Baz as Qux } from 'changed';",
- "import Default, { Foo, Bar, Baz as Qux, } from 'changed';",
- "import Default, { Foo as Bar, Baz as Qux, Norf } from 'changed';",
- "import Default, { Foo as Bar, Baz as Qux, Norf, } from 'changed';",
- "import Default, { Foo as Bar, Baz, Qux as Norf } from 'changed';",
- "import Default, { Foo as Bar, Baz, Qux as Norf, } from 'changed';",
- "import Default, { Foo, Bar as Baz, Qux as Norf } from 'changed';",
- "import Default, { Foo, Bar as Baz, Qux as Norf, } from 'changed';",
- "import Default, { Foo as Bar, Baz as Qux, Norf as NoMore } from 'changed';",
- "import Default, { Foo as Bar, Baz as Qux, Norf as NoMore, } from 'changed';",
- "import Default , { } from 'changed';",
- 'import "changed";',
- 'import Default from "changed";',
- 'import * as All from "changed";',
- 'import { } from "changed";',
- 'import { Foo } from "changed";',
- 'import { Foo, } from "changed";',
- 'import { Foo as Bar } from "changed";',
- 'import { Foo as Bar, } from "changed";',
- 'import { Foo, Bar } from "changed";',
- 'import { Foo, Bar, } from "changed";',
- 'import { Foo as Bar, Baz } from "changed";',
- 'import { Foo as Bar, Baz, } from "changed";',
- 'import { Foo, Bar as Baz } from "changed";',
- 'import { Foo, Bar as Baz, } from "changed";',
- 'import { Foo as Bar, Baz as Qux } from "changed";',
- 'import { Foo as Bar, Baz as Qux, } from "changed";',
- 'import { Foo, Bar, Baz } from "changed";',
- 'import { Foo, Bar, Baz, } from "changed";',
- 'import { Foo as Bar, Baz, Qux } from "changed";',
- 'import { Foo as Bar, Baz, Qux, } from "changed";',
- 'import { Foo, Bar as Baz, Qux } from "changed";',
- 'import { Foo, Bar as Baz, Qux, } from "changed";',
- 'import { Foo, Bar, Baz as Qux } from "changed";',
- 'import { Foo, Bar, Baz as Qux, } from "changed";',
- 'import { Foo as Bar, Baz as Qux, Norf } from "changed";',
- 'import { Foo as Bar, Baz as Qux, Norf, } from "changed";',
- 'import { Foo as Bar, Baz, Qux as Norf } from "changed";',
- 'import { Foo as Bar, Baz, Qux as Norf, } from "changed";',
- 'import { Foo, Bar as Baz, Qux as Norf } from "changed";',
- 'import { Foo, Bar as Baz, Qux as Norf, } from "changed";',
- 'import { Foo as Bar, Baz as Qux, Norf as NoMore } from "changed";',
- 'import { Foo as Bar, Baz as Qux, Norf as NoMore, } from "changed";',
- 'import Default, * as All from "changed";',
- 'import Default, { } from "changed";',
- 'import Default, { Foo } from "changed";',
- 'import Default, { Foo, } from "changed";',
- 'import Default, { Foo as Bar } from "changed";',
- 'import Default, { Foo as Bar, } from "changed";',
- 'import Default, { Foo, Bar } from "changed";',
- 'import Default, { Foo, Bar, } from "changed";',
- 'import Default, { Foo as Bar, Baz } from "changed";',
- 'import Default, { Foo as Bar, Baz, } from "changed";',
- 'import Default, { Foo, Bar as Baz } from "changed";',
- 'import Default, { Foo, Bar as Baz, } from "changed";',
- 'import Default, { Foo as Bar, Baz as Qux } from "changed";',
- 'import Default, { Foo as Bar, Baz as Qux, } from "changed";',
- 'import Default, { Foo, Bar, Baz } from "changed";',
- 'import Default, { Foo, Bar, Baz, } from "changed";',
- 'import Default, { Foo as Bar, Baz, Qux } from "changed";',
- 'import Default, { Foo as Bar, Baz, Qux, } from "changed";',
- 'import Default, { Foo, Bar as Baz, Qux } from "changed";',
- 'import Default, { Foo, Bar as Baz, Qux, } from "changed";',
- 'import Default, { Foo, Bar, Baz as Qux } from "changed";',
- 'import Default, { Foo, Bar, Baz as Qux, } from "changed";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf } from "changed";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf, } from "changed";',
- 'import Default, { Foo as Bar, Baz, Qux as Norf } from "changed";',
- 'import Default, { Foo as Bar, Baz, Qux as Norf, } from "changed";',
- 'import Default, { Foo, Bar as Baz, Qux as Norf } from "changed";',
- 'import Default, { Foo, Bar as Baz, Qux as Norf, } from "changed";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf } from "changed";',
- 'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf, } from "changed";',
- 'import Default from "Y";',
- 'import * as All from \'z\';',
- // import with support for new lines
- "import { Foo,\n Bar }\n from 'changed';",
- "import { \nFoo,\nBar,\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz\n }\n from 'changed';",
- "import { \nFoo as Bar,\n Baz\n, }\n from 'changed';",
- "import { Foo,\n Bar as Baz\n }\n from 'changed';",
- "import { Foo,\n Bar as Baz,\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz as Qux\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz as Qux,\n }\n from 'changed';",
- "import { Foo,\n Bar,\n Baz }\n from 'changed';",
- "import { Foo,\n Bar,\n Baz,\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz,\n Qux\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz,\n Qux,\n }\n from 'changed';",
- "import { Foo,\n Bar as Baz,\n Qux\n }\n from 'changed';",
- "import { Foo,\n Bar as Baz,\n Qux,\n }\n from 'changed';",
- "import { Foo,\n Bar,\n Baz as Qux\n }\n from 'changed';",
- "import { Foo,\n Bar,\n Baz as Qux,\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz,\n Qux as Norf\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz,\n Qux as Norf,\n }\n from 'changed';",
- "import { Foo,\n Bar as Baz,\n Qux as Norf\n }\n from 'changed';",
- "import { Foo,\n Bar as Baz,\n Qux as Norf,\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf as Enuf\n }\n from 'changed';",
- "import { Foo as Bar,\n Baz as Qux,\n Norf as Enuf,\n }\n from 'changed';",
- "import Default,\n * as All from 'changed';",
- "import Default,\n { } from 'changed';",
- "import Default,\n { Foo\n }\n from 'changed';",
- "import Default,\n { Foo,\n }\n from 'changed';",
- "import Default,\n { Foo as Bar\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar\n } from\n 'changed';",
- "import Default,\n { Foo,\n Bar,\n } from\n 'changed';",
- "import Default,\n { Foo as Bar,\n Baz\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz,\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar as Baz\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar as Baz,\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz as Qux\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar,\n Baz\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar,\n Baz,\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux,\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar as Baz,\n Qux\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar as Baz,\n Qux,\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar,\n Baz as Qux\n }\n from 'changed';",
- "import Default,\n { Foo,\n Bar,\n Baz as Qux,\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux as Norf }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz,\n Qux as Norf, }\n from 'changed';",
- "import Default,\n { Foo, Bar as Baz,\n Qux as Norf }\n from 'changed';",
- "import Default,\n { Foo, Bar as Baz,\n Qux as Norf, }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore\n }\n from 'changed';",
- "import Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore,\n }\n from 'changed';",
- "import Default\n , { } from 'changed';",
- // single line export
- "export'x';",
- "export 'changed';",
- "export 'changed' ;",
- "export Default from 'changed';",
- "export * as All from 'changed';",
- "export {} from 'changed';",
- "export { } from 'changed';",
- "export {Foo} from 'changed';",
- "export { Foo } from 'changed';",
- "export { Foo, } from 'changed';",
- "export {Foo as Bar} from 'changed';",
- "export { Foo as Bar } from 'changed';",
- "export { Foo as Bar, } from 'changed';",
- "export { Foo, Bar } from 'changed';",
- "export { Foo, Bar, } from 'changed';",
- "export { Foo as Bar, Baz } from 'changed';",
- "export { Foo as Bar, Baz, } from 'changed';",
- "export { Foo, Bar as Baz } from 'changed';",
- "export { Foo, Bar as Baz, } from 'changed';",
- "export { Foo as Bar, Baz as Qux } from 'changed';",
- "export { Foo as Bar, Baz as Qux, } from 'changed';",
- "export { Foo, Bar, Baz } from 'changed';",
- "export { Foo, Bar, Baz, } from 'changed';",
- "export { Foo as Bar, Baz, Qux } from 'changed';",
- "export { Foo as Bar, Baz, Qux, } from 'changed';",
- "export { Foo, Bar as Baz, Qux } from 'changed';",
- "export { Foo, Bar as Baz, Qux, } from 'changed';",
- "export { Foo, Bar, Baz as Qux } from 'changed';",
- "export { Foo, Bar, Baz as Qux, } from 'changed';",
- "export { Foo as Bar, Baz as Qux, Norf } from 'changed';",
- "export { Foo as Bar, Baz as Qux, Norf, } from 'changed';",
- "export { Foo as Bar, Baz, Qux as Norf } from 'changed';",
- "export { Foo as Bar, Baz, Qux as Norf, } from 'changed';",
- "export { Foo, Bar as Baz, Qux as Norf } from 'changed';",
- "export { Foo, Bar as Baz, Qux as Norf, } from 'changed';",
- "export { Foo as Bar, Baz as Qux, Norf as Enuf } from 'changed';",
- "export { Foo as Bar, Baz as Qux, Norf as Enuf, } from 'changed';",
- "export Default, * as All from 'changed';",
- "export Default, { } from 'changed';",
- "export Default, { Foo } from 'changed';",
- "export Default, { Foo, } from 'changed';",
- "export Default, { Foo as Bar } from 'changed';",
- "export Default, { Foo as Bar, } from 'changed';",
- "export Default, { Foo, Bar } from 'changed';",
- "export Default, { Foo, Bar, } from 'changed';",
- "export Default, { Foo as Bar, Baz } from 'changed';",
- "export Default, { Foo as Bar, Baz, } from 'changed';",
- "export Default, { Foo, Bar as Baz } from 'changed';",
- "export Default, { Foo, Bar as Baz, } from 'changed';",
- "export Default, { Foo as Bar, Baz as Qux } from 'changed';",
- "export Default, { Foo as Bar, Baz as Qux, } from 'changed';",
- "export Default, { Foo, Bar, Baz } from 'changed';",
- "export Default, { Foo, Bar, Baz, } from 'changed';",
- "export Default, { Foo as Bar, Baz, Qux } from 'changed';",
- "export Default, { Foo as Bar, Baz, Qux, } from 'changed';",
- "export Default, { Foo, Bar as Baz, Qux } from 'changed';",
- "export Default, { Foo, Bar as Baz, Qux, } from 'changed';",
- "export Default, { Foo, Bar, Baz as Qux } from 'changed';",
- "export Default, { Foo, Bar, Baz as Qux, } from 'changed';",
- "export Default, { Foo as Bar, Baz as Qux, Norf } from 'changed';",
- "export Default, { Foo as Bar, Baz as Qux, Norf, } from 'changed';",
- "export Default, { Foo as Bar, Baz, Qux as Norf } from 'changed';",
- "export Default, { Foo as Bar, Baz, Qux as Norf, } from 'changed';",
- "export Default, { Foo, Bar as Baz, Qux as Norf } from 'changed';",
- "export Default, { Foo, Bar as Baz, Qux as Norf, } from 'changed';",
- "export Default, { Foo as Bar, Baz as Qux, Norf as NoMore } from 'changed';",
- "export Default, { Foo as Bar, Baz as Qux, Norf as NoMore, } from 'changed';",
- "export Default , { } from 'changed';",
- 'export "changed";',
- 'export Default from "changed";',
- 'export * as All from "changed";',
- 'export { } from "changed";',
- 'export { Foo } from "changed";',
- 'export { Foo, } from "changed";',
- 'export { Foo as Bar } from "changed";',
- 'export { Foo as Bar, } from "changed";',
- 'export { Foo, Bar } from "changed";',
- 'export { Foo, Bar, } from "changed";',
- 'export { Foo as Bar, Baz } from "changed";',
- 'export { Foo as Bar, Baz, } from "changed";',
- 'export { Foo, Bar as Baz } from "changed";',
- 'export { Foo, Bar as Baz, } from "changed";',
- 'export { Foo as Bar, Baz as Qux } from "changed";',
- 'export { Foo as Bar, Baz as Qux, } from "changed";',
- 'export { Foo, Bar, Baz } from "changed";',
- 'export { Foo, Bar, Baz, } from "changed";',
- 'export { Foo as Bar, Baz, Qux } from "changed";',
- 'export { Foo as Bar, Baz, Qux, } from "changed";',
- 'export { Foo, Bar as Baz, Qux } from "changed";',
- 'export { Foo, Bar as Baz, Qux, } from "changed";',
- 'export { Foo, Bar, Baz as Qux } from "changed";',
- 'export { Foo, Bar, Baz as Qux, } from "changed";',
- 'export { Foo as Bar, Baz as Qux, Norf } from "changed";',
- 'export { Foo as Bar, Baz as Qux, Norf, } from "changed";',
- 'export { Foo as Bar, Baz, Qux as Norf } from "changed";',
- 'export { Foo as Bar, Baz, Qux as Norf, } from "changed";',
- 'export { Foo, Bar as Baz, Qux as Norf } from "changed";',
- 'export { Foo, Bar as Baz, Qux as Norf, } from "changed";',
- 'export { Foo as Bar, Baz as Qux, Norf as NoMore } from "changed";',
- 'export { Foo as Bar, Baz as Qux, Norf as NoMore, } from "changed";',
- 'export Default, * as All from "changed";',
- 'export Default, { } from "changed";',
- 'export Default, { Foo } from "changed";',
- 'export Default, { Foo, } from "changed";',
- 'export Default, { Foo as Bar } from "changed";',
- 'export Default, { Foo as Bar, } from "changed";',
- 'export Default, { Foo, Bar } from "changed";',
- 'export Default, { Foo, Bar, } from "changed";',
- 'export Default, { Foo as Bar, Baz } from "changed";',
- 'export Default, { Foo as Bar, Baz, } from "changed";',
- 'export Default, { Foo, Bar as Baz } from "changed";',
- 'export Default, { Foo, Bar as Baz, } from "changed";',
- 'export Default, { Foo as Bar, Baz as Qux } from "changed";',
- 'export Default, { Foo as Bar, Baz as Qux, } from "changed";',
- 'export Default, { Foo, Bar, Baz } from "changed";',
- 'export Default, { Foo, Bar, Baz, } from "changed";',
- 'export Default, { Foo as Bar, Baz, Qux } from "changed";',
- 'export Default, { Foo as Bar, Baz, Qux, } from "changed";',
- 'export Default, { Foo, Bar as Baz, Qux } from "changed";',
- 'export Default, { Foo, Bar as Baz, Qux, } from "changed";',
- 'export Default, { Foo, Bar, Baz as Qux } from "changed";',
- 'export Default, { Foo, Bar, Baz as Qux, } from "changed";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf } from "changed";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf, } from "changed";',
- 'export Default, { Foo as Bar, Baz, Qux as Norf } from "changed";',
- 'export Default, { Foo as Bar, Baz, Qux as Norf, } from "changed";',
- 'export Default, { Foo, Bar as Baz, Qux as Norf } from "changed";',
- 'export Default, { Foo, Bar as Baz, Qux as Norf, } from "changed";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf as Enuf } from "changed";',
- 'export Default, { Foo as Bar, Baz as Qux, Norf as Enuf, } from "changed";',
- 'export Default from "Y";',
- 'export * as All from \'z\';',
- // export with support for new lines
- "export { Foo,\n Bar }\n from 'changed';",
- "export { \nFoo,\nBar,\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz\n }\n from 'changed';",
- "export { \nFoo as Bar,\n Baz\n, }\n from 'changed';",
- "export { Foo,\n Bar as Baz\n }\n from 'changed';",
- "export { Foo,\n Bar as Baz,\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz as Qux\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz as Qux,\n }\n from 'changed';",
- "export { Foo,\n Bar,\n Baz }\n from 'changed';",
- "export { Foo,\n Bar,\n Baz,\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz,\n Qux\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz,\n Qux,\n }\n from 'changed';",
- "export { Foo,\n Bar as Baz,\n Qux\n }\n from 'changed';",
- "export { Foo,\n Bar as Baz,\n Qux,\n }\n from 'changed';",
- "export { Foo,\n Bar,\n Baz as Qux\n }\n from 'changed';",
- "export { Foo,\n Bar,\n Baz as Qux,\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz,\n Qux as Norf\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz,\n Qux as Norf,\n }\n from 'changed';",
- "export { Foo,\n Bar as Baz,\n Qux as Norf\n }\n from 'changed';",
- "export { Foo,\n Bar as Baz,\n Qux as Norf,\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf as Enuf\n }\n from 'changed';",
- "export { Foo as Bar,\n Baz as Qux,\n Norf as Enuf,\n }\n from 'changed';",
- "export Default,\n * as All from 'changed';",
- "export Default,\n { } from 'changed';",
- "export Default,\n { Foo\n }\n from 'changed';",
- "export Default,\n { Foo,\n }\n from 'changed';",
- "export Default,\n { Foo as Bar\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar\n } from\n 'changed';",
- "export Default,\n { Foo,\n Bar,\n } from\n 'changed';",
- "export Default,\n { Foo as Bar,\n Baz\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz,\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar as Baz\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar as Baz,\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz as Qux\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar,\n Baz\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar,\n Baz,\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux,\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar as Baz,\n Qux\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar as Baz,\n Qux,\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar,\n Baz as Qux\n }\n from 'changed';",
- "export Default,\n { Foo,\n Bar,\n Baz as Qux,\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf,\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux as Norf }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz,\n Qux as Norf, }\n from 'changed';",
- "export Default,\n { Foo, Bar as Baz,\n Qux as Norf }\n from 'changed';",
- "export Default,\n { Foo, Bar as Baz,\n Qux as Norf, }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore\n }\n from 'changed';",
- "export Default,\n { Foo as Bar,\n Baz as Qux,\n Norf as NoMore,\n }\n from 'changed';",
- "export Default\n , { } from 'changed';",
+ module: createModule('test module', ['x', 'y']),
+ name: 'test module',
+ code,
+ meta: {dependencyOffsets}
+ }).then(({code: processedCode}) => {
+ expect(processedCode).toEqual([
+ '__d("test module", function(global, require, module, exports) {' +
// require
'require("changed")',
'require("Y")',
@@ -1045,6 +323,22 @@ describe('Resolver', function() {
});
});
+ pit('should pass through passed-in source maps', () => {
+ const module = createModule('test module');
+ const resolutionResponse = new ResolutionResponseMock({
+ dependencies: [module],
+ mainModuleId: 'test module',
+ });
+ const inputMap = {version: 3, mappings: 'ARBITRARY'};
+ return new Resolver({projectRoot: '/root'}).wrapModule({
+ resolutionResponse,
+ module,
+ name: 'test module',
+ code: 'arbitrary(code)',
+ map: inputMap,
+ }).then(({map}) => expect(map).toBe(inputMap));
+ });
+
pit('should resolve polyfills', function () {
const depResolver = new Resolver({
projectRoot: '/root',
@@ -1053,17 +347,90 @@ describe('Resolver', function() {
const code = [
'global.fetch = () => 1;',
].join('');
- return depResolver.wrapModule(
- null,
- polyfill,
+ return depResolver.wrapModule({
+ module: polyfill,
code
- ).then(processedCode => {
- expect(processedCode.code).toEqual([
+ }).then(({code: processedCode}) => {
+ expect(processedCode).toEqual([
'(function(global) {',
'global.fetch = () => 1;',
"\n})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);",
].join(''));
});
});
+
+ describe('JSON files:', () => {
+ const code = JSON.stringify({arbitrary: "data"});
+ const id = 'arbitrary.json';
+ let depResolver, module, resolutionResponse;
+
+ beforeEach(() => {
+ depResolver = new Resolver({projectRoot: '/root'});
+ module = createJsonModule(id);
+ resolutionResponse = new ResolutionResponseMock({
+ dependencies: [module],
+ mainModuleId: id,
+ });
+ });
+
+ pit('should prefix JSON files with `module.exports=`', () => {
+ return depResolver
+ .wrapModule({resolutionResponse, module, name: id, code})
+ .then(({code: processedCode}) =>
+ expect(processedCode).toEqual([
+ `__d(${JSON.stringify(id)}, function(global, require, module, exports) {`,
+ `module.exports = ${code}\n});`,
+ ].join('')));
+ });
+ });
+
+ describe('minification:', () => {
+ const code ='arbitrary(code)';
+ const id = 'arbitrary.js';
+ let depResolver, minifyCode, module, resolutionResponse, sourceMap;
+
+ beforeEach(() => {
+ minifyCode = jest.genMockFn().mockImpl((filename, code, map) =>
+ Promise.resolve({code, map}));
+ depResolver = new Resolver({
+ projectRoot: '/root',
+ minifyCode
+ });
+ module = createModule(id);
+ module.path = '/arbitrary/path.js';
+ resolutionResponse = new ResolutionResponseMock({
+ dependencies: [module],
+ mainModuleId: id,
+ });
+ sourceMap = {version: 3, sources: ['input'], mappings: 'whatever'};
+ });
+
+ pit('should invoke the minifier with the wrapped code', () => {
+ const wrappedCode = `__d("${id}", function(global, require, module, exports) {${code}\n});`
+ return depResolver
+ .wrapModule({
+ resolutionResponse,
+ module,
+ name: id,
+ code,
+ map: sourceMap,
+ minify: true
+ }).then(() => {
+ expect(minifyCode).toBeCalledWith(module.path, wrappedCode, sourceMap);
+ });
+ });
+
+ pit('should use minified code', () => {
+ const minifiedCode = 'minified(code)';
+ const minifiedMap = {version: 3, file: ['minified']};
+ minifyCode.mockReturnValue(Promise.resolve({code: minifiedCode, map: minifiedMap}));
+ return depResolver
+ .wrapModule({resolutionResponse, module, name: id, code, minify: true})
+ .then(({code, map}) => {
+ expect(code).toEqual(minifiedCode);
+ expect(map).toEqual(minifiedMap);
+ });
+ });
+ });
});
});
diff --git a/packager/react-packager/src/Resolver/index.js b/packager/react-packager/src/Resolver/index.js
index d60e0fb2b..707402fac 100644
--- a/packager/react-packager/src/Resolver/index.js
+++ b/packager/react-packager/src/Resolver/index.js
@@ -12,7 +12,6 @@
const path = require('path');
const Activity = require('../Activity');
const DependencyGraph = require('node-haste');
-const replacePatterns = require('node-haste').replacePatterns;
const declareOpts = require('../lib/declareOpts');
const Promise = require('promise');
@@ -48,6 +47,12 @@ const validateOpts = declareOpts({
type: 'object',
required: true,
},
+ transformCode: {
+ type: 'function',
+ },
+ minifyCode: {
+ type: 'function',
+ },
});
const getDependenciesValidateOpts = declareOpts({
@@ -97,8 +102,10 @@ class Resolver {
fileWatcher: opts.fileWatcher,
cache: opts.cache,
shouldThrowOnUnresolvedErrors: (_, platform) => platform === 'ios',
+ transformCode: opts.transformCode,
});
+ this._minifyCode = opts.minifyCode;
this._polyfillModuleNames = opts.polyfillModuleNames || [];
this._depGraph.load().catch(err => {
@@ -119,12 +126,14 @@ class Resolver {
return this._depGraph.getModuleForPath(entryFile);
}
- getDependencies(entryPath, options) {
+ getDependencies(entryPath, options, transformOptions, onProgress) {
const {platform, recursive} = getDependenciesValidateOpts(options);
return this._depGraph.getDependencies({
entryPath,
platform,
+ transformOptions,
recursive,
+ onProgress,
}).then(resolutionResponse => {
this._getPolyfillDependencies().reverse().forEach(
polyfill => resolutionResponse.prependDependency(polyfill)
@@ -176,16 +185,14 @@ class Resolver {
);
}
- resolveRequires(resolutionResponse, module, code) {
+ resolveRequires(resolutionResponse, module, code, dependencyOffsets = []) {
return Promise.resolve().then(() => {
- if (module.isPolyfill()) {
- return Promise.resolve({code});
- }
-
const resolvedDeps = Object.create(null);
const resolvedDepsArr = [];
return Promise.all(
+ // here, we build a map of all require strings (relative and absolute)
+ // to the canonical name of the module they reference
resolutionResponse.getResolvedDependencyPairs(module).map(
([depName, depModule]) => {
if (depModule) {
@@ -197,59 +204,81 @@ class Resolver {
}
)
).then(() => {
- const relativizeCode = (codeMatch, pre, quot, depName, post) => {
+ const relativizeCode = (codeMatch, quot, depName) => {
+ // if we have a canonical name for the module imported here,
+ // we use it, so that require() is always called with the same
+ // id for every module.
+ // Example:
+ // -- in a/b.js:
+ // require('./c') => require('a/c');
+ // -- in b/index.js:
+ // require('../a/c') => require('a/c');
const depId = resolvedDeps[depName];
if (depId) {
- return pre + quot + depId + post;
+ return quot + depId + quot;
} else {
return codeMatch;
}
};
- code = code
- .replace(replacePatterns.IMPORT_RE, relativizeCode)
- .replace(replacePatterns.EXPORT_RE, relativizeCode)
- .replace(replacePatterns.REQUIRE_RE, relativizeCode);
+ code = dependencyOffsets.reduceRight((codeBits, offset) => {
+ const first = codeBits.shift();
+ codeBits.unshift(
+ first.slice(0, offset),
+ first.slice(offset).replace(/(['"])([^'"']*)\1/, relativizeCode),
+ );
+ return codeBits;
+ }, [code]);
- return module.getName().then(name => {
- return {name, code};
- });
+ return code.join('');
});
});
}
- wrapModule(resolutionResponse, module, code) {
- if (module.isPolyfill()) {
- return Promise.resolve({
- code: definePolyfillCode(code),
- });
+ wrapModule({
+ resolutionResponse,
+ module,
+ name,
+ map,
+ code,
+ meta = {},
+ minify = false
+ }) {
+ if (module.isJSON()) {
+ code = `module.exports = ${code}`;
}
+ const result = module.isPolyfill()
+ ? Promise.resolve({code: definePolyfillCode(code)})
+ : this.resolveRequires(
+ resolutionResponse,
+ module,
+ code,
+ meta.dependencyOffsets
+ ).then(code => ({code: defineModuleCode(name, code), map}));
- return this.resolveRequires(resolutionResponse, module, code).then(
- ({name, code}) => {
- return {name, code: defineModuleCode(name, code)};
- });
+ return minify
+ ? result.then(({code, map}) => this._minifyCode(module.path, code, map))
+ : result;
}
getDebugInfo() {
return this._depGraph.getDebugInfo();
}
-
}
function defineModuleCode(moduleName, code) {
return [
`__d(`,
- `'${moduleName}',`,
- 'function(global, require, module, exports) {',
- ` ${code}`,
+ `${JSON.stringify(moduleName)}, `,
+ `function(global, require, module, exports) {`,
+ `${code}`,
'\n});',
].join('');
}
-function definePolyfillCode(code) {
+function definePolyfillCode(code,) {
return [
- '(function(global) {',
+ `(function(global) {`,
code,
`\n})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);`,
].join('');
diff --git a/packager/react-packager/src/Server/index.js b/packager/react-packager/src/Server/index.js
index 5949bd0c7..c1f20606e 100644
--- a/packager/react-packager/src/Server/index.js
+++ b/packager/react-packager/src/Server/index.js
@@ -73,10 +73,6 @@ const validateOpts = declareOpts({
type: 'string',
required: false,
},
- disableInternalTransforms: {
- type: 'boolean',
- default: false,
- },
});
const bundleOpts = declareOpts({
@@ -146,6 +142,10 @@ const dependencyOpts = declareOpts({
type: 'boolean',
default: true,
},
+ hot: {
+ type: 'boolean',
+ default: false,
+ },
});
class Server {
@@ -259,12 +259,7 @@ class Server {
}
const opts = dependencyOpts(options);
- return this._bundler.getDependencies(
- opts.entryFile,
- opts.dev,
- opts.platform,
- opts.recursive,
- );
+ return this._bundler.getDependencies(opts);
});
}
diff --git a/packager/react-packager/src/lib/ModuleTransport.js b/packager/react-packager/src/lib/ModuleTransport.js
index afb660d38..8ba0aaea8 100644
--- a/packager/react-packager/src/lib/ModuleTransport.js
+++ b/packager/react-packager/src/lib/ModuleTransport.js
@@ -21,11 +21,7 @@ function ModuleTransport(data) {
this.sourcePath = data.sourcePath;
this.virtual = data.virtual;
-
- if (this.virtual && data.map) {
- throw new Error('Virtual modules cannot have source maps');
- }
-
+ this.meta = data.meta;
this.map = data.map;
Object.freeze(this);
diff --git a/packager/react-packager/src/transforms/whole-program-optimisations/__tests__/dead-module-elimination-test.js b/packager/react-packager/src/transforms/whole-program-optimisations/__tests__/dead-module-elimination-test.js
deleted file mode 100644
index 4d7d142c4..000000000
--- a/packager/react-packager/src/transforms/whole-program-optimisations/__tests__/dead-module-elimination-test.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * 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';
-
-jest.autoMockOff();
-
-var deadModuleElimintation = require('../dead-module-elimination');
-var babel = require('babel-core');
-
-const compile = (code) =>
- babel.transform(code, {
- plugins: [deadModuleElimintation],
- }).code;
-
-const compare = (source, output) => {
- const out = trim(compile(source))
- // workaround babel/source map bug
- .replace(/^false;/, '');
-
- expect(out).toEqual(trim(output));
-};
-
-
-const trim = (str) =>
- str.replace(/\s/g, '');
-
-describe('dead-module-elimination', () => {
- it('should inline __DEV__', () => {
- compare(
- `global.__DEV__ = false;
- var foo = __DEV__;`,
- `var foo = false;`
- );
- });
-
- it('should accept unary operators with literals', () => {
- compare(
- `global.__DEV__ = !1;
- var foo = __DEV__;`,
- `var foo = false;`
- );
- });
-
- it('should kill dead branches', () => {
- compare(
- `global.__DEV__ = false;
- if (__DEV__) {
- doSomething();
- }`,
- ``
- );
- });
-
- it('should kill unreferenced modules', () => {
- compare(
- `__d('foo', function() {})`,
- ``
- );
- });
-
- it('should kill unreferenced modules at multiple levels', () => {
- compare(
- `__d('bar', function() {});
- __d('foo', function() { require('bar'); });`,
- ``
- );
- });
-
- it('should kill modules referenced only from dead branches', () => {
- compare(
- `global.__DEV__ = false;
- __d('bar', function() {});
- if (__DEV__) { require('bar'); }`,
- ``
- );
- });
-
- it('should replace logical expressions with the result', () => {
- compare(
- `global.__DEV__ = false;
- __d('bar', function() {});
- __DEV__ && require('bar');`,
- `false;`
- );
- });
-
- it('should keep if result branch', () => {
- compare(
- `global.__DEV__ = false;
- __d('bar', function() {});
- if (__DEV__) {
- killWithFire();
- } else {
- require('bar');
- }`,
- `__d('bar', function() {});
- require('bar');`
- );
- });
-
- it('should replace falsy ternaries with alternate expression', () => {
- compare(
- `global.__DEV__ = false;
- __DEV__ ? foo() : bar();
- `,
- `bar();`
- );
- });
-});
diff --git a/packager/react-packager/src/transforms/whole-program-optimisations/dead-module-elimination.js b/packager/react-packager/src/transforms/whole-program-optimisations/dead-module-elimination.js
deleted file mode 100644
index b5f33b4e0..000000000
--- a/packager/react-packager/src/transforms/whole-program-optimisations/dead-module-elimination.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/**
- * 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 t = require('babel-types');
-
-var globals = Object.create(null);
-var requires = Object.create(null);
-var _requires;
-
-const hasDeadModules = modules =>
- Object.keys(modules).some(key => modules[key] === 0);
-
-function CallExpression(path) {
- const { node } = path;
- const fnName = node.callee.name;
-
- if (fnName === 'require' || fnName === '__d') {
- var moduleName = node.arguments[0].value;
- if (fnName === '__d' && _requires && !_requires[moduleName]) {
- path.remove();
- } else if (fnName === '__d'){
- requires[moduleName] = requires[moduleName] || 0;
- } else {
- requires[moduleName] = (requires[moduleName] || 0) + 1;
- }
- }
-}
-
-function IfStatement(path) {
- const { node } = path;
-
- if (node.test.type === 'Identifier' && node.test.name in globals) {
- if (globals[node.test.name]) {
- if (node.consequent.type === 'BlockStatement') {
- path.replaceWithMultiple(node.consequent.body);
- } else {
- path.replaceWith(node.consequent);
- }
- } else if (node.alternate) {
- if (node.alternate.type === 'BlockStatement') {
- path.replaceWithMultiple(node.alternate.body);
- } else {
- path.replaceWith(node.alternate);
- }
- } else {
- path.remove();
- }
- }
- }
-
-module.exports = function () {
- var firstPass = {
- AssignmentExpression(path) {
- const { node } = path;
-
- if (
- node.left.type === 'MemberExpression' &&
- node.left.object.name === 'global' &&
- node.left.property.type === 'Identifier' &&
- node.left.property.name === '__DEV__'
- ) {
- var value;
- if (node.right.type === 'BooleanLiteral') {
- value = node.right.value;
- } else if (
- node.right.type === 'UnaryExpression' &&
- node.right.operator === '!' &&
- node.right.argument.type === 'NumericLiteral'
- ) {
- value = !node.right.argument.value;
- } else {
- return;
- }
- globals[node.left.property.name] = value;
-
- // workaround babel/source map bug - the minifier should strip it
- path.replaceWith(t.booleanLiteral(value));
-
- //path.remove();
- //scope.removeBinding(node.left.name);
- }
- },
- IfStatement,
- ConditionalExpression: IfStatement,
- Identifier(path) {
- const { node } = path;
-
- var parent = path.parent;
- if (parent.type === 'AssignmentExpression' && parent.left === node) {
- return;
- }
-
- if (node.name in globals) {
- path.replaceWith(t.booleanLiteral(globals[node.name]));
- }
- },
-
- CallExpression,
-
- LogicalExpression(path) {
- const { node } = path;
-
- if (node.left.type === 'Identifier' && node.left.name in globals) {
- const value = globals[node.left.name];
-
- if (node.operator === '&&') {
- if (value) {
- path.replaceWith(node.right);
- } else {
- path.replaceWith(t.booleanLiteral(value));
- }
- } else if (node.operator === '||') {
- if (value) {
- path.replaceWith(t.booleanLiteral(value));
- } else {
- path.replaceWith(node.right);
- }
- }
- }
- }
- };
-
- var secondPass = {
- CallExpression,
- };
-
- return {
- visitor: {
- Program(path) {
- path.traverse(firstPass);
- var counter = 0;
- while (hasDeadModules(requires) && counter < 3) {
- _requires = requires;
- requires = {};
- path.traverse(secondPass);
- counter++;
- }
- }
- }
- };
-};
diff --git a/packager/react-packager/src/transforms/whole-program-optimisations/index.js b/packager/react-packager/src/transforms/whole-program-optimisations/index.js
deleted file mode 100644
index f802c0f77..000000000
--- a/packager/react-packager/src/transforms/whole-program-optimisations/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * 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';
-
-// Return the list of plugins use for Whole Program Optimisations
-module.exports = [
- require('./dead-module-elimination'),
-];
diff --git a/packager/transformer.js b/packager/transformer.js
index 071f4007f..18da16f28 100644
--- a/packager/transformer.js
+++ b/packager/transformer.js
@@ -61,7 +61,7 @@ const getBabelRC = (function() {
}
return babelRC;
- }
+ };
})();
/**
@@ -81,14 +81,16 @@ function buildBabelConfig(filename, options) {
// Add extra plugins
const extraPlugins = [externalHelpersPlugin];
- if (options.inlineRequires) {
+ var inlineRequires = options.inlineRequires;
+ var blacklist = inlineRequires && inlineRequires.blacklist;
+ if (inlineRequires && !(blacklist && filename in blacklist)) {
extraPlugins.push(inlineRequiresPlugin);
}
config.plugins = extraPlugins.concat(config.plugins);
if (options.hot) {
- const hmrConfig = makeHMRConfig(options);
+ const hmrConfig = makeHMRConfig(options, filename);
config = Object.assign({}, config, hmrConfig);
}
@@ -102,7 +104,9 @@ function transform(src, filename, options) {
const result = babel.transform(src, babelConfig);
return {
+ ast: result.ast,
code: result.code,
+ map: result.map,
filename: filename,
};
}