Move wrapModule logic for scripts, modules and JSON files to the transformer

Reviewed By: davidaurelio

Differential Revision: D6389116

fbshipit-source-id: fa43bd54669849c22b6b9d155ab07676b2455ef7
This commit is contained in:
Rafael Oleza 2017-11-23 15:33:45 -08:00 committed by Facebook Github Bot
parent b193fc3436
commit b08ce130fd
14 changed files with 529 additions and 704 deletions

View File

@ -213,6 +213,7 @@ class Bundler {
module.path,
module.localPath,
code,
module.isPolyfill(),
transformCodeOptions,
),
transformCache: opts.transformCache,
@ -240,14 +241,11 @@ class Bundler {
}
async generateAssetObjAndCode(
module: Module,
path: string,
assetPlugins: Array<string>,
platform: ?string = null,
) {
const assetData = await this._assetServer.getAssetData(
module.path,
platform,
);
const assetData = await this._assetServer.getAssetData(path, platform);
const asset = await this._applyAssetPlugins(assetPlugins, assetData);
const {

View File

@ -14,6 +14,7 @@
const DeltaCalculator = require('./DeltaCalculator');
const addParamsToDefineCall = require('../lib/addParamsToDefineCall');
const createModuleIdFactory = require('../lib/createModuleIdFactory');
const {EventEmitter} = require('events');
@ -425,27 +426,37 @@ class DeltaTransformer extends EventEmitter {
): Promise<[number, ?DeltaEntry]> {
const name = module.getName();
const metadata = await this._getMetadata(module, transformOptions);
const edge = dependencyEdges.get(module.path);
const dependencyPairs = edge ? edge.dependencies : new Map();
const wrapped = this._resolver.wrapModule({
module,
getModuleId: this._getModuleId,
dependencyPairs,
dependencyOffsets: metadata.dependencyOffsets || [],
name,
code: metadata.code,
map: metadata.map,
dev: this._bundleOptions.dev,
});
let wrappedCode;
if (module.isAsset()) {
wrappedCode = await this._wrapAsset({
code: metadata.code,
dependencyPairs,
name,
path: module.path,
});
} else if (!module.isPolyfill()) {
wrappedCode = this._addDependencyMap({
code: metadata.code,
dependencyPairs,
name,
path: module.path,
});
} else {
wrappedCode = metadata.code;
}
const {code, map} = transformOptions.minify
? await this._resolver.minifyModule(
module.path,
wrapped.code,
wrapped.map,
wrappedCode,
metadata.map,
)
: wrapped;
: {code: wrappedCode, map: metadata.map};
const id = this._getModuleId(module.path);
@ -463,6 +474,70 @@ class DeltaTransformer extends EventEmitter {
];
}
/**
* Function to add the mapping object between local module ids and
* actual bundle module ids for dependencies. This way, we can do the path
* replacements on require() calls on transformers (since local ids do not
* change between bundles).
*/
_addDependencyMap({
code,
dependencyPairs,
name,
path,
}: {
code: string,
dependencyPairs: Map<string, string>,
name: string,
path: string,
}): string {
const moduleId = this._getModuleId(path);
const params = [
moduleId,
Array.from(dependencyPairs.values()).map(this._getModuleId),
];
// Add the module name as the last parameter (to make it easier to do
// requires by name when debugging).
if (this._bundleOptions.dev) {
params.push(name);
}
return addParamsToDefineCall(code, ...params);
}
/**
* Temporary function to wrap an asset. This logic will go away once we
* generate the needed JS code for assets in the transformer.
*/
async _wrapAsset({
code,
dependencyPairs,
name,
path,
}: {
code: string,
dependencyPairs: Map<string, string>,
name: string,
path: string,
}): Promise<string> {
const asset = await this._bundler.generateAssetObjAndCode(
path,
this._bundleOptions.assetPlugins,
this._bundleOptions.platform,
);
return await this._resolver.wrapModule({
path,
getModuleId: this._getModuleId,
dependencyPairs,
dependencyOffsets: asset.meta.dependencyOffsets,
name,
code: asset.code,
dev: this._bundleOptions.dev,
});
}
_getModuleType(module: Module): DeltaEntryType {
if (module.isAsset()) {
return 'asset';
@ -480,25 +555,10 @@ class DeltaTransformer extends EventEmitter {
transformOptions: JSTransformerOptions,
): Promise<{
+code: string,
+dependencyOffsets: ?Array<number>,
+dependencies: Array<string>,
+map: CompactRawMappings,
+source: string,
}> {
if (module.isAsset()) {
const asset = await this._bundler.generateAssetObjAndCode(
module,
this._bundleOptions.assetPlugins,
this._bundleOptions.platform,
);
return {
code: asset.code,
dependencyOffsets: asset.meta.dependencyOffsets,
map: [],
source: '',
};
}
return await module.read(transformOptions);
}

View File

@ -59,6 +59,7 @@ describe('Transformer', function() {
fileName,
localPath,
code,
false,
transformOptions,
);
@ -67,6 +68,7 @@ describe('Transformer', function() {
fileName,
localPath,
code,
false,
transformOptions,
);
});
@ -92,7 +94,7 @@ describe('Transformer', function() {
expect.assertions(6);
return transformer
.transformFile(fileName, localPath, '', {})
.transformFile(fileName, localPath, '', true, {})
.catch(function(error) {
expect(error.type).toEqual('TransformError');
expect(error.message).toBe(

View File

@ -87,6 +87,7 @@ module.exports = class Transformer {
filename: string,
localPath: LocalPath,
code: string,
isScript: boolean,
options: Options,
): Promise<TransformedCode> {
try {
@ -97,6 +98,7 @@ module.exports = class Transformer {
filename,
localPath,
code,
isScript,
options,
);

View File

@ -13,243 +13,95 @@
jest
.mock('../constant-folding')
.mock('../extract-dependencies')
.mock('../inline')
.mock('../minify')
.mock('babel-generator');
.mock('../minify');
const {objectContaining} = jasmine;
const path = require('path');
const transformCode = require('..').transformAndExtractDependencies;
describe('code transformation worker:', () => {
let transformCode;
let babelGenerator;
let extractDependencies, transformer;
beforeEach(() => {
jest.resetModules();
({transformCode} = require('..'));
extractDependencies = require('../extract-dependencies').mockReturnValue(
{},
);
transformer = {
transform: jest.fn(({filename, options, src}) => ({
code: src,
map: [],
})),
};
babelGenerator = require('babel-generator');
babelGenerator.default.mockReturnValue({
code: '',
map: [],
});
});
it('calls the transform with file name, source code, and transform options', function() {
const filename = 'arbitrary/file.js';
const localPath = `local/${filename}`;
const sourceCode = 'arbitrary(code)';
const transformOptions = {arbitrary: 'options'};
transformCode(transformer, filename, localPath, sourceCode, {
dev: true,
transform: transformOptions,
});
expect(transformer.transform).toBeCalledWith({
filename,
localPath,
options: transformOptions,
plugins: [],
src: sourceCode,
});
});
it('calls the transform with two plugins when not in dev mode', () => {
const filename = 'arbitrary/file.js';
const localPath = `local/${filename}`;
const sourceCode = 'arbitrary(code)';
const options = {dev: false, transform: {arbitrary: 'options'}};
transformCode(transformer, filename, localPath, sourceCode, options);
const plugins = transformer.transform.mock.calls[0][0].plugins;
expect(plugins[0]).toEqual([expect.any(Object), options]);
expect(plugins[1]).toEqual([expect.any(Object), options]);
});
it('prefixes JSON files with an assignment to module.exports to make the code valid', function() {
const filename = 'arbitrary/file.json';
const localPath = `local/${filename}`;
const sourceCode = '{"arbitrary":"property"}';
transformCode(transformer, filename, localPath, sourceCode, {dev: true});
expect(transformer.transform).toBeCalledWith({
filename,
localPath,
options: undefined,
plugins: [],
src: `module.exports=${sourceCode}`,
});
});
it('calls back with the result of the transform in the cache', async () => {
const result = {
code: 'some.other(code)',
map: [],
};
babelGenerator.default.mockReturnValue({
code: 'some.other(code)',
map: [],
});
const data = await transformCode(
transformer,
'filename',
'local/filename',
result.code,
{},
it('transforms a simple script', async () => {
const {result} = await transformCode(
path.join(__dirname, '../../../transformer.js'),
'arbitrary/file.js',
`local/file.js`,
'someReallyArbitrary(code)',
true,
{
dev: true,
transform: {},
},
);
expect(data.result).toEqual(objectContaining(result));
expect(result.code).toBe(
[
'(function (global) {',
' someReallyArbitrary(code);',
'})(this);',
].join('\n'),
);
expect(result.map).toHaveLength(3);
expect(result.dependencies).toEqual([]);
});
it('removes the leading `module.exports` before returning if the file is a JSON file, even if minified', async () => {
const code = '{a:1,b:2}';
const filePath = 'arbitrary/file.json';
babelGenerator.default.mockReturnValue({
code: '{a:1,b:2}',
map: [],
});
const data = await transformCode(transformer, filePath, filePath, code, {});
expect(data.result.code).toEqual(code);
});
it('removes shebang when present', async () => {
const shebang = '#!/usr/bin/env node';
const result = {
code: `${shebang} \n arbitrary(code)`,
};
const filePath = 'arbitrary/file.js';
babelGenerator.default.mockReturnValue({
code: `${shebang} \n arbitrary(code)`,
map: [],
});
const data = await transformCode(
transformer,
filePath,
filePath,
result.code,
{},
it('transforms a simple module', async () => {
const {result} = await transformCode(
path.join(__dirname, '../../../transformer.js'),
'arbitrary/file.js',
`local/file.js`,
'arbitrary(code)',
false,
{
dev: true,
transform: {},
},
);
const {code} = data.result;
expect(code).not.toContain(shebang);
expect(code.split('\n').length).toEqual(result.code.split('\n').length);
expect(result.code).toBe(
[
'__d(function (global, require, module, exports, _dependencyMap) {',
' arbitrary(code);',
'});',
].join('\n'),
);
expect(result.map).toHaveLength(3);
expect(result.dependencies).toEqual([]);
});
it('calls back with any error yielded by the transform', async () => {
const message = 'SyntaxError: this code is broken.';
it('transforms a module with dependencies', async () => {
const {result} = await transformCode(
path.join(__dirname, '../../../transformer.js'),
'arbitrary/file.js',
`local/file.js`,
[
'require("./a");',
'arbitrary(code);',
'const b = require("b");',
'import c from "./c";',
].join('\n'),
false,
{
dev: true,
transform: {},
},
);
transformer.transform.mockImplementation(() => {
throw new Error(message);
});
expect.assertions(1);
try {
await transformCode(
transformer,
'filename',
'local/filename',
'code',
{},
);
} catch (error) {
expect(error.message).toBe(message);
}
});
describe('dependency extraction', () => {
it('passes the transformed code the `extractDependencies`', async () => {
const code = 'arbitrary(code)';
babelGenerator.default.mockReturnValue({
code: 'arbitrary(code)',
map: [],
});
await transformCode(transformer, 'filename', 'local/filename', code, {});
expect(extractDependencies).toBeCalledWith(code, 'filename');
});
it('uses `dependencies` and `dependencyOffsets` provided by `extractDependencies` for the result', async () => {
const dependencyData = {
dependencies: ['arbitrary', 'list', 'of', 'dependencies'],
dependencyOffsets: [12, 119, 185, 328, 471],
};
extractDependencies.mockReturnValue(dependencyData);
const data = await transformCode(
transformer,
'filename',
'local/filename',
'code',
{},
);
expect(data.result).toEqual(objectContaining(dependencyData));
});
it('does not extract requires of JSON files', async () => {
const jsonStr = '{"arbitrary":"json"}';
babelGenerator.default.mockReturnValue({
code: '{"arbitrary":"json"}',
map: [],
});
const data = await transformCode(
transformer,
'arbitrary.json',
'local/arbitrary.json',
jsonStr,
{},
);
const {dependencies, dependencyOffsets} = data.result;
expect(extractDependencies).not.toBeCalled();
expect(dependencies).toEqual([]);
expect(dependencyOffsets).toEqual([]);
});
it('calls back with every error thrown by `extractDependencies`', async () => {
const error = new Error('arbitrary');
extractDependencies.mockImplementation(() => {
throw error;
});
try {
await transformCode(
transformer,
'arbitrary.js',
'local/arbitrary.js',
'code',
{},
);
} catch (err) {
expect(err).toBe(error);
}
});
expect(result.code).toBe(
[
'__d(function (global, require, module, exports, _dependencyMap) {',
' var _c = require(_dependencyMap[0], "./c");',
'',
' var _c2 = babelHelpers.interopRequireDefault(_c);',
'',
' require(_dependencyMap[1], "./a");',
'',
' arbitrary(code);',
'',
' var b = require(_dependencyMap[2], "b");',
'});',
].join('\n'),
);
expect(result.map).toHaveLength(13);
expect(result.dependencies).toEqual(['./c', './a', 'b']);
});
});

View File

@ -12,28 +12,25 @@
'use strict';
const JsFileWrapping = require('../../ModuleGraph/worker/JsFileWrapping');
const collectDependencies = require('../../ModuleGraph/worker/collect-dependencies');
const constantFolding = require('./constant-folding');
const extractDependencies = require('./extract-dependencies');
const generate = require('babel-generator').default;
const inline = require('./inline');
const minify = require('./minify');
const {compactMapping, toRawMappings} = require('../../Bundler/source-map');
const {compactMapping} = require('../../Bundler/source-map');
import type {LogEntry} from '../../Logger/Types';
import type {
CompactRawMappings,
MappingsMap,
RawMappings,
} from '../../lib/SourceMap';
import type {CompactRawMappings, MappingsMap} from '../../lib/SourceMap';
import type {LocalPath} from '../../node-haste/lib/toLocalPath';
import type {ResultWithMap} from './minify';
import type {Ast, Plugins as BabelPlugins} from 'babel-core';
export type TransformedCode = {
code: string,
dependencies: Array<string>,
dependencyOffsets: Array<number>,
dependencies: $ReadOnlyArray<string>,
map: CompactRawMappings,
};
@ -96,6 +93,7 @@ async function transformCode(
filename: string,
localPath: LocalPath,
sourceCode: string,
isScript: boolean,
options: Options,
): Promise<Data> {
const isJson = filename.endsWith('.json');
@ -116,7 +114,7 @@ async function transformCode(
? []
: [[inline.plugin, options], [constantFolding.plugin, options]];
const result = await transformer.transform({
const {ast} = await transformer.transform({
filename,
localPath,
options: options.transform,
@ -124,9 +122,45 @@ async function transformCode(
src: sourceCode,
});
// Serialize the AST received from the transformer.
const transformed = generate(
result.ast,
const timeDelta = process.hrtime(transformFileStartLogEntry.start_timestamp);
const duration_ms = Math.round((timeDelta[0] * 1e9 + timeDelta[1]) / 1e6);
const transformFileEndLogEntry = {
action_name: 'Transforming file',
action_phase: 'end',
file_name: filename,
duration_ms,
log_entry_label: 'Transforming file',
};
let dependencies, wrappedAst;
// If the module to transform is a script (meaning that is not part of the
// dependency graph and it code will just be prepended to the bundle modules),
// we need to wrap it differently than a commonJS module (also, scripts do
// not have dependencies).
if (isScript) {
dependencies = [];
wrappedAst = JsFileWrapping.wrapPolyfill(ast);
} else {
let dependencyData = collectDependencies(ast);
if (!options.dev) {
dependencyData = collectDependencies.forOptimization(
ast,
dependencyData.dependencies,
dependencyData.dependencyMapName,
);
}
dependencies = dependencyData.dependencies.map(dep => dep.name);
wrappedAst = JsFileWrapping.wrapModule(
ast,
dependencyData.dependencyMapName,
);
}
const result = generate(
wrappedAst,
{
code: false,
comments: false,
@ -139,40 +173,10 @@ async function transformCode(
sourceCode,
);
// If the transformer returns standard sourcemaps, we need to transform them
// to rawMappings so we can process them correctly.
const rawMappings =
transformed.map && !Array.isArray(transformed.map)
? toRawMappings(transformed.map)
: transformed.map;
// Convert the sourcemaps to Compact Raw source maps.
const map = rawMappings ? rawMappings.map(compactMapping) : [];
let code = transformed.code;
if (isJson) {
code = code.replace(/^\w+\.exports=/, '');
} else {
// Remove shebang
code = code.replace(/^#!.*/, '');
}
const depsResult = isJson
? {dependencies: [], dependencyOffsets: []}
: extractDependencies(code, filename);
const timeDelta = process.hrtime(transformFileStartLogEntry.start_timestamp);
const duration_ms = Math.round((timeDelta[0] * 1e9 + timeDelta[1]) / 1e6);
const transformFileEndLogEntry = {
action_name: 'Transforming file',
action_phase: 'end',
file_name: filename,
duration_ms,
log_entry_label: 'Transforming file',
};
const map = result.rawMappings ? result.rawMappings.map(compactMapping) : [];
return {
result: {...depsResult, code, map},
result: {dependencies, code: result.code, map},
transformFileStartLogEntry,
transformFileEndLogEntry,
};
@ -201,6 +205,7 @@ exports.transformAndExtractDependencies = async function(
filename: string,
localPath: LocalPath,
sourceCode: string,
isScript: boolean,
options: Options,
): Promise<Data> {
// $FlowFixMe: impossible to type a dynamic require.
@ -211,6 +216,7 @@ exports.transformAndExtractDependencies = async function(
filename,
localPath,
sourceCode,
isScript,
options,
);
};

View File

@ -133,7 +133,14 @@ function createMapLookup(dependencyMapIdentifier, propertyIdentifier) {
);
}
function collectDependencies(ast, replacement, dependencyMapIdentifier) {
function collectDependencies(
ast,
replacement,
dependencyMapIdentifier,
): {
dependencies: $ReadOnlyArray<TransformResultDependency>,
dependencyMapName: string,
} {
const visited = new WeakSet();
const traversalState = {dependencyMapIdentifier};
traverse(

View File

@ -161,8 +161,8 @@ describe('Resolver', function() {
dependencyPairs.set(relativePath, dependencyModule.path);
}
const {code: processedCode} = depResolver.wrapModule({
module: module,
const processedCode = depResolver.wrapModule({
path: module.path,
getModuleId: resolutionResponse.getModuleId,
dependencyPairs,
name: 'test module',
@ -201,11 +201,11 @@ describe('Resolver', function() {
mainModuleId: 'test module',
});
const {code: processedCode} = depResolver.wrapModule({
const processedCode = depResolver.wrapModule({
getModuleId: resolutionResponse.getModuleId,
dependencyPairs: resolutionResponse.getResolvedDependencyPairs(module),
code,
module,
path: module.path,
name: 'test module',
dev: true,
});
@ -220,90 +220,6 @@ describe('Resolver', function() {
);
});
it('should pass through passed-in source maps', () => {
expect.assertions(1);
const module = createModule('test module');
const resolutionResponse = new ResolutionResponseMock({
dependencies: [module],
mainModuleId: 'test module',
});
const inputMap = {version: 3, mappings: 'ARBITRARY'};
const {map} = depResolver.wrapModule({
getModuleId: resolutionResponse.getModuleId,
dependencyPairs: resolutionResponse.getResolvedDependencyPairs(module),
module,
name: 'test module',
code: 'arbitrary(code)',
map: inputMap,
});
expect(map).toBe(inputMap);
});
it('should resolve polyfills', async function() {
expect.assertions(1);
return Resolver.load({
projectRoot: '/root',
}).then(depResolver => {
const polyfill = createPolyfill('test polyfill', []);
const code = ['global.fetch = () => 1;'].join('');
const {code: processedCode} = depResolver.wrapModule({
module: polyfill,
code,
});
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(() => {
return Resolver.load({projectRoot: '/root'}).then(r => {
depResolver = r;
module = createJsonModule(id);
resolutionResponse = new ResolutionResponseMock({
dependencies: [module],
mainModuleId: id,
});
});
});
it('should prefix JSON files with `module.exports=`', () => {
expect.assertions(1);
const {code: processedCode} = depResolver.wrapModule({
getModuleId: resolutionResponse.getModuleId,
dependencyPairs: resolutionResponse.getResolvedDependencyPairs(
module,
),
module,
name: id,
code,
dev: false,
});
expect(processedCode).toEqual(
[
`__d(/* ${id} */function(global, require, module, exports) {`,
`module.exports = ${code}\n}, ${resolutionResponse.getModuleId(
module.path,
)});`,
].join(''),
);
});
});
describe('minification:', () => {
const code = 'arbitrary(code)';
const id = 'arbitrary.js';

View File

@ -120,7 +120,6 @@ class Resolver {
}
resolveRequires(
module: Module,
getModuleId: (path: string) => number,
code: string,
dependencyPairs: Map<string, string>,
@ -154,44 +153,30 @@ class Resolver {
}
wrapModule({
module,
path,
getModuleId,
dependencyPairs,
dependencyOffsets,
name,
map,
code,
dev = true,
}: {
module: Module,
path: string,
getModuleId: (path: string) => number,
dependencyPairs: Map<string, string>,
dependencyOffsets: Array<number>,
name: string,
map: CompactRawMappings,
code: string,
dev?: boolean,
}): {code: string, map: CompactRawMappings} {
if (module.isJSON()) {
code = `module.exports = ${code}`;
}
}): string {
code = this.resolveRequires(
getModuleId,
code,
dependencyPairs,
dependencyOffsets,
);
if (module.isPolyfill()) {
code = definePolyfillCode(code);
} else {
const moduleId = getModuleId(module.path);
code = this.resolveRequires(
module,
getModuleId,
code,
dependencyPairs,
dependencyOffsets,
);
code = defineModuleCode(moduleId, code, name, dev);
}
return {code, map};
return defineModuleCode(getModuleId(path), code, name, dev);
}
async minifyModule(

View File

@ -1,325 +1,337 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`basic_bundle bundles package with polyfills 1`] = `
"(function(global) {
"(function (global) {
global.__DEV__ = false;
global.__BUNDLE_START_TIME__ = global.nativePerformanceNow ? global.nativePerformanceNow() : Date.now();
})(this);
(function (global) {
'use strict';
global.__DEV__ = false;
global.require = _require;
global.__d = define;
var modules = Object.create(null);
global.__BUNDLE_START_TIME__ = global.nativePerformanceNow ? global.nativePerformanceNow() : Date.now();
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
(function(global) {
function define(factory, moduleId, dependencyMap) {
if (moduleId in modules) {
return;
}
'use strict';
global.require = _require;
global.__d = define;
var modules = Object.create(null);
function define(factory, moduleId, dependencyMap) {
if (moduleId in modules) {
return;
modules[moduleId] = {
dependencyMap: dependencyMap,
exports: undefined,
factory: factory,
hasError: false,
isInitialized: false
};
}
modules[moduleId] = {
dependencyMap: dependencyMap,
exports: undefined,
factory: factory,
hasError: false,
isInitialized: false
};
}
function _require(moduleId) {
var moduleIdReallyIsNumber = moduleId;
var module = modules[moduleIdReallyIsNumber];
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
}
function _require(moduleId) {
var moduleIdReallyIsNumber = moduleId;
var module = modules[moduleIdReallyIsNumber];
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
}
var inGuard = false;
function guardedLoadModule(moduleId, module) {
if (!inGuard && global.ErrorUtils) {
inGuard = true;
var returnValue = void 0;
try {
returnValue = loadModuleImplementation(moduleId, module);
} catch (e) {
global.ErrorUtils.reportFatalError(e);
}
inGuard = false;
return returnValue;
} else {
return loadModuleImplementation(moduleId, module);
}
}
var ID_MASK_SHIFT = 16;
var LOCAL_ID_MASK = ~0 >>> ID_MASK_SHIFT;
function unpackModuleId(moduleId) {
var segmentId = moduleId >>> ID_MASK_SHIFT;
var localId = moduleId & LOCAL_ID_MASK;
return {
segmentId: segmentId,
localId: localId
};
}
_require.unpackModuleId = unpackModuleId;
function loadModuleImplementation(moduleId, module) {
var nativeRequire = global.nativeRequire;
if (!module && nativeRequire) {
var _unpackModuleId = unpackModuleId(moduleId),
segmentId = _unpackModuleId.segmentId,
localId = _unpackModuleId.localId;
nativeRequire(localId, segmentId);
module = modules[moduleId];
}
if (!module) {
throw unknownModuleError(moduleId);
}
if (module.hasError) {
throw moduleThrewError(moduleId, module.error);
}
module.isInitialized = true;
var exports = module.exports = {};
var _module = module,
factory = _module.factory,
dependencyMap = _module.dependencyMap;
var inGuard = false;
function guardedLoadModule(moduleId, module) {
if (!inGuard && global.ErrorUtils) {
inGuard = true;
var returnValue = void 0;
try {
returnValue = loadModuleImplementation(moduleId, module);
var _moduleObject = {
exports: exports
};
factory(global, _require, _moduleObject, exports, dependencyMap);
{
module.factory = undefined;
module.dependencyMap = undefined;
}
return module.exports = _moduleObject.exports;
} catch (e) {
global.ErrorUtils.reportFatalError(e);
module.hasError = true;
module.error = e;
module.isInitialized = false;
module.exports = undefined;
throw e;
}
inGuard = false;
return returnValue;
} else {
return loadModuleImplementation(moduleId, module);
}
}
var ID_MASK_SHIFT = 16;
var LOCAL_ID_MASK = ~0 >>> ID_MASK_SHIFT;
function unpackModuleId(moduleId) {
var segmentId = moduleId >>> ID_MASK_SHIFT;
var localId = moduleId & LOCAL_ID_MASK;
return { segmentId: segmentId, localId: localId };
}
_require.unpackModuleId = unpackModuleId;
function loadModuleImplementation(moduleId, module) {
var nativeRequire = global.nativeRequire;
if (!module && nativeRequire) {
var _unpackModuleId = unpackModuleId(moduleId),
segmentId = _unpackModuleId.segmentId,
localId = _unpackModuleId.localId;
nativeRequire(localId, segmentId);
module = modules[moduleId];
}
if (!module) {
throw unknownModuleError(moduleId);
function unknownModuleError(id) {
var message = 'Requiring unknown module \\"' + id + '\\".';
return Error(message);
}
if (module.hasError) {
throw moduleThrewError(moduleId, module.error);
function moduleThrewError(id, error) {
var displayName = id;
return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error);
}
})(this);
(function (global) {
'use strict';
module.isInitialized = true;
var exports = module.exports = {};
var _module = module,
factory = _module.factory,
dependencyMap = _module.dependencyMap;
try {
var _moduleObject = { exports: exports };
factory(global, _require, _moduleObject, exports, dependencyMap);
{
module.factory = undefined;
module.dependencyMap = undefined;
}
return module.exports = _moduleObject.exports;
} catch (e) {
module.hasError = true;
module.error = e;
module.isInitialized = false;
module.exports = undefined;
throw e;
if (!Object.keys) {
Object.keys = function () {};
}
}
})(this);
(function (global) {
'use strict';
function unknownModuleError(id) {
var message = 'Requiring unknown module \\"' + id + '\\".';
if (!String.prototype.repeat) {
String.prototype.repeat = function () {};
}
})(this);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
return Error(message);
}
var Bar = require(_dependencyMap[0]);
function moduleThrewError(id, error) {
var displayName = id;
return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error);
}
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
(function(global) {
var Foo = require(_dependencyMap[1]);
'use strict';
module.exports = {
Foo: Foo,
Bar: Bar
};
},4,[5,6]);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
if (!Object.keys) {
Object.keys = function () {};
}
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
(function(global) {
var Foo = require(_dependencyMap[0]);
'use strict';
module.exports = {
type: 'bar',
foo: Foo.type
};
},5,[6]);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
if (!String.prototype.repeat) {
String.prototype.repeat = function () {};
}
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
__d(/* /TestBundle.js */function(global, require, module, exports) {
var asset = require(_dependencyMap[0]);
'use strict';
var Bar = require(5); // 5 = ./Bar
var Foo = require(6); // 6 = ./Foo
module.exports = { Foo: Foo, Bar: Bar };
}, 4);
__d(/* /Bar.js */function(global, require, module, exports) {
'use strict';
var Foo = require(6); // 6 = ./Foo
module.exports = { type: 'bar', foo: Foo.type };
}, 5);
__d(/* /Foo.js */function(global, require, module, exports) {
'use strict';
var asset = require(7); // 7 = ./test.png
module.exports = { type: 'foo', asset: asset };
}, 6);
module.exports = {
type: 'foo',
asset: asset
};
},6,[7]);
__d(/* /test.png */function(global, require, module, exports) {module.exports=require(8).registerAsset({\\"__packager_asset\\":true,\\"httpServerLocation\\":\\"/assets\\",\\"width\\":8,\\"height\\":8,\\"scales\\":[1],\\"hash\\":\\"77d45c1f7fa73c0f6c444a830dc42f67\\",\\"name\\":\\"test\\",\\"type\\":\\"png\\"}); // 8 = /AssetRegistry
}, 7);
__d(/* /AssetRegistry.js */function(global, require, module, exports) {
'use strict';
}, 8);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
},8,[]);
require(4);"
`;
exports[`basic_bundle bundles package without polyfills 1`] = `
"(function(global) {
"(function (global) {
global.__DEV__ = false;
global.__BUNDLE_START_TIME__ = global.nativePerformanceNow ? global.nativePerformanceNow() : Date.now();
})(this);
(function (global) {
'use strict';
global.__DEV__ = false;
global.require = _require;
global.__d = define;
var modules = Object.create(null);
global.__BUNDLE_START_TIME__ = global.nativePerformanceNow ? global.nativePerformanceNow() : Date.now();
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
(function(global) {
function define(factory, moduleId, dependencyMap) {
if (moduleId in modules) {
return;
}
'use strict';
global.require = _require;
global.__d = define;
var modules = Object.create(null);
function define(factory, moduleId, dependencyMap) {
if (moduleId in modules) {
return;
modules[moduleId] = {
dependencyMap: dependencyMap,
exports: undefined,
factory: factory,
hasError: false,
isInitialized: false
};
}
modules[moduleId] = {
dependencyMap: dependencyMap,
exports: undefined,
factory: factory,
hasError: false,
isInitialized: false
};
}
function _require(moduleId) {
var moduleIdReallyIsNumber = moduleId;
var module = modules[moduleIdReallyIsNumber];
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
}
function _require(moduleId) {
var moduleIdReallyIsNumber = moduleId;
var module = modules[moduleIdReallyIsNumber];
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
}
var inGuard = false;
function guardedLoadModule(moduleId, module) {
if (!inGuard && global.ErrorUtils) {
inGuard = true;
var returnValue = void 0;
try {
returnValue = loadModuleImplementation(moduleId, module);
} catch (e) {
global.ErrorUtils.reportFatalError(e);
}
inGuard = false;
return returnValue;
} else {
return loadModuleImplementation(moduleId, module);
}
}
var ID_MASK_SHIFT = 16;
var LOCAL_ID_MASK = ~0 >>> ID_MASK_SHIFT;
function unpackModuleId(moduleId) {
var segmentId = moduleId >>> ID_MASK_SHIFT;
var localId = moduleId & LOCAL_ID_MASK;
return {
segmentId: segmentId,
localId: localId
};
}
_require.unpackModuleId = unpackModuleId;
function loadModuleImplementation(moduleId, module) {
var nativeRequire = global.nativeRequire;
if (!module && nativeRequire) {
var _unpackModuleId = unpackModuleId(moduleId),
segmentId = _unpackModuleId.segmentId,
localId = _unpackModuleId.localId;
nativeRequire(localId, segmentId);
module = modules[moduleId];
}
if (!module) {
throw unknownModuleError(moduleId);
}
if (module.hasError) {
throw moduleThrewError(moduleId, module.error);
}
module.isInitialized = true;
var exports = module.exports = {};
var _module = module,
factory = _module.factory,
dependencyMap = _module.dependencyMap;
var inGuard = false;
function guardedLoadModule(moduleId, module) {
if (!inGuard && global.ErrorUtils) {
inGuard = true;
var returnValue = void 0;
try {
returnValue = loadModuleImplementation(moduleId, module);
var _moduleObject = {
exports: exports
};
factory(global, _require, _moduleObject, exports, dependencyMap);
{
module.factory = undefined;
module.dependencyMap = undefined;
}
return module.exports = _moduleObject.exports;
} catch (e) {
global.ErrorUtils.reportFatalError(e);
module.hasError = true;
module.error = e;
module.isInitialized = false;
module.exports = undefined;
throw e;
}
inGuard = false;
return returnValue;
} else {
return loadModuleImplementation(moduleId, module);
}
}
var ID_MASK_SHIFT = 16;
var LOCAL_ID_MASK = ~0 >>> ID_MASK_SHIFT;
function unpackModuleId(moduleId) {
var segmentId = moduleId >>> ID_MASK_SHIFT;
var localId = moduleId & LOCAL_ID_MASK;
return { segmentId: segmentId, localId: localId };
}
_require.unpackModuleId = unpackModuleId;
function loadModuleImplementation(moduleId, module) {
var nativeRequire = global.nativeRequire;
if (!module && nativeRequire) {
var _unpackModuleId = unpackModuleId(moduleId),
segmentId = _unpackModuleId.segmentId,
localId = _unpackModuleId.localId;
nativeRequire(localId, segmentId);
module = modules[moduleId];
}
if (!module) {
throw unknownModuleError(moduleId);
function unknownModuleError(id) {
var message = 'Requiring unknown module \\"' + id + '\\".';
return Error(message);
}
if (module.hasError) {
throw moduleThrewError(moduleId, module.error);
function moduleThrewError(id, error) {
var displayName = id;
return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error);
}
})(this);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
module.isInitialized = true;
var exports = module.exports = {};
var _module = module,
factory = _module.factory,
dependencyMap = _module.dependencyMap;
var Bar = require(_dependencyMap[0]);
try {
var Foo = require(_dependencyMap[1]);
var _moduleObject = { exports: exports };
module.exports = {
Foo: Foo,
Bar: Bar
};
},2,[3,4]);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
factory(global, _require, _moduleObject, exports, dependencyMap);
var Foo = require(_dependencyMap[0]);
{
module.factory = undefined;
module.dependencyMap = undefined;
}
module.exports = {
type: 'bar',
foo: Foo.type
};
},3,[4]);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
return module.exports = _moduleObject.exports;
} catch (e) {
module.hasError = true;
module.error = e;
module.isInitialized = false;
module.exports = undefined;
throw e;
}
}
var asset = require(_dependencyMap[0]);
function unknownModuleError(id) {
var message = 'Requiring unknown module \\"' + id + '\\".';
return Error(message);
}
function moduleThrewError(id, error) {
var displayName = id;
return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error);
}
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
__d(/* /TestBundle.js */function(global, require, module, exports) {
'use strict';
var Bar = require(3); // 3 = ./Bar
var Foo = require(4); // 4 = ./Foo
module.exports = { Foo: Foo, Bar: Bar };
}, 2);
__d(/* /Bar.js */function(global, require, module, exports) {
'use strict';
var Foo = require(4); // 4 = ./Foo
module.exports = { type: 'bar', foo: Foo.type };
}, 3);
__d(/* /Foo.js */function(global, require, module, exports) {
'use strict';
var asset = require(5); // 5 = ./test.png
module.exports = { type: 'foo', asset: asset };
}, 4);
module.exports = {
type: 'foo',
asset: asset
};
},4,[5]);
__d(/* /test.png */function(global, require, module, exports) {module.exports=require(6).registerAsset({\\"__packager_asset\\":true,\\"httpServerLocation\\":\\"/assets\\",\\"width\\":8,\\"height\\":8,\\"scales\\":[1],\\"hash\\":\\"77d45c1f7fa73c0f6c444a830dc42f67\\",\\"name\\":\\"test\\",\\"type\\":\\"png\\"}); // 6 = /AssetRegistry
}, 5);
__d(/* /AssetRegistry.js */function(global, require, module, exports) {
'use strict';
}, 6);
__d(function (global, require, module, exports, _dependencyMap) {
'use strict';
},6,[]);
require(2);"
`;

View File

@ -212,9 +212,7 @@ function validateCachedResult(cachedResult: mixed): ?CachedResult {
typeof cachedResult === 'object' &&
typeof cachedResult.code === 'string' &&
Array.isArray(cachedResult.dependencies) &&
cachedResult.dependencies.every(dep => typeof dep === 'string') &&
Array.isArray(cachedResult.dependencyOffsets) &&
cachedResult.dependencyOffsets.every(offset => typeof offset === 'number')
cachedResult.dependencies.every(dep => typeof dep === 'string')
) {
return (cachedResult: any);
}

View File

@ -33,8 +33,7 @@ const CACHE_SUB_DIR = 'cache';
export type CachedResult = {
code: string,
dependencies: Array<string>,
dependencyOffsets: Array<number>,
dependencies: $ReadOnlyArray<string>,
map: CompactRawMappings,
};
@ -143,7 +142,6 @@ class FileBasedCache {
.digest('hex'),
hashSourceCode(props),
result.dependencies,
result.dependencyOffsets,
result.map,
]),
);
@ -214,7 +212,6 @@ class FileBasedCache {
result: {
code: transformedCode,
dependencies: metadata.dependencies,
dependencyOffsets: metadata.dependencyOffsets,
map: metadata.sourceMap,
},
outdatedDependencies: EMPTY_ARRAY,
@ -335,7 +332,6 @@ function readMetadataFileSync(
cachedResultHash: string,
cachedSourceHash: string,
dependencies: Array<string>,
dependencyOffsets: Array<number>,
sourceMap: CompactRawMappings,
} {
const metadataStr = fs.readFileSync(metadataFilePath, 'utf8');
@ -347,7 +343,6 @@ function readMetadataFileSync(
cachedResultHash,
cachedSourceHash,
dependencies,
dependencyOffsets,
sourceMap,
] = metadata;
if (
@ -357,10 +352,6 @@ function readMetadataFileSync(
Array.isArray(dependencies) &&
dependencies.every(dep => typeof dep === 'string')
) ||
!(
Array.isArray(dependencyOffsets) &&
dependencyOffsets.every(offset => typeof offset === 'number')
) ||
!(sourceMap == null || typeof sourceMap === 'object')
) {
return null;
@ -369,7 +360,6 @@ function readMetadataFileSync(
cachedResultHash,
cachedSourceHash,
dependencies,
dependencyOffsets,
sourceMap,
};
}

View File

@ -71,7 +71,6 @@ describe('TransformCaching.FileBasedCache', () => {
result: {
code: `/* result for ${key} */`,
dependencies: ['foo', `dep of ${key}`],
dependencyOffsets: [12, 34],
map: {desc: `source map for ${key}`},
},
};
@ -104,7 +103,6 @@ describe('TransformCaching.FileBasedCache', () => {
result: {
code: `/* result for ${key} */`,
dependencies: ['foo', 'bar'],
dependencyOffsets: [12, 34],
map: {desc: `source map for ${key}`},
},
};

View File

@ -39,8 +39,7 @@ import type {LocalPath} from './lib/toLocalPath';
export type ReadResult = {
+code: string,
+dependencies: Array<string>,
+dependencyOffsets?: ?Array<number>,
+dependencies: $ReadOnlyArray<string>,
+map: CompactRawMappings,
+source: string,
};