Reviewed By: jeanlauliac

Differential Revision: D4628330

fbshipit-source-id: 94fad1294e22fa0073e15843f94241ae778112a0
This commit is contained in:
Christoph Pojer 2017-03-01 08:05:59 -08:00 коммит произвёл Facebook Github Bot
Родитель 04f42ab075
Коммит 4d00df41b4
23 изменённых файлов: 176 добавлений и 179 удалений

Просмотреть файл

@ -29,7 +29,7 @@ function escapeRegExp(pattern) {
} else if (typeof pattern === 'string') {
var escaped = pattern.replace(/[\-\[\]\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
// convert the '/' into an escaped local file separator
return escaped.replace(/\//g,'\\' + path.sep);
return escaped.replace(/\//g, '\\' + path.sep);
} else {
throw new Error('Unexpected packager blacklist pattern: ' + pattern);
}

Просмотреть файл

@ -12,7 +12,6 @@ jest.disableAutomock();
const Bundle = require('../Bundle');
const ModuleTransport = require('../../lib/ModuleTransport');
const SourceMapGenerator = require('source-map').SourceMapGenerator;
const crypto = require('crypto');
describe('Bundle', () => {
@ -107,33 +106,37 @@ describe('Bundle', () => {
});
});
it('should insert modules in a deterministic order, independent from timing of the wrapping process', () => {
const moduleTransports = [
createModuleTransport({name: 'module1'}),
createModuleTransport({name: 'module2'}),
createModuleTransport({name: 'module3'}),
];
it('inserts modules in a deterministic order, independent of timing of the wrapper process',
() => {
const moduleTransports = [
createModuleTransport({name: 'module1'}),
createModuleTransport({name: 'module2'}),
createModuleTransport({name: 'module3'}),
];
const resolves = {};
const resolver = {
wrapModule({name}) {
return new Promise(resolve => resolves[name] = resolve);
},
};
const resolves = {};
const resolver = {
wrapModule({name}) {
return new Promise(resolve => {
resolves[name] = resolve;
});
},
};
const promise = Promise.all(
moduleTransports.map(m => bundle.addModule(resolver, null, {isPolyfill: () => false}, m)))
.then(() => {
expect(bundle.getModules())
.toEqual(moduleTransports);
});
const promise = Promise.all(moduleTransports.map(
m => bundle.addModule(resolver, null, {isPolyfill: () => false}, m)
)).then(() => {
expect(bundle.getModules())
.toEqual(moduleTransports);
});
resolves.module2({code: ''});
resolves.module3({code: ''});
resolves.module1({code: ''});
resolves.module2({code: ''});
resolves.module3({code: ''});
resolves.module1({code: ''});
return promise;
});
return promise;
},
);
});
describe('sourcemap bundle', () => {
@ -268,7 +271,6 @@ describe('Bundle', () => {
describe('getEtag()', function() {
it('should return an etag', function() {
var bundle = new Bundle({sourceMapUrl: 'test_url'});
bundle.finalize({});
var eTag = crypto.createHash('md5').update(bundle.getSource()).digest('hex');
expect(bundle.getEtag()).toEqual(eTag);

Просмотреть файл

@ -38,7 +38,10 @@ const VERSION = require('../../package.json').version;
import type AssetServer from '../AssetServer';
import type Module, {HasteImpl} from '../node-haste/Module';
import type ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse';
import type {Options as JSTransformerOptions, TransformOptions} from '../JSTransformer/worker/worker';
import type {
Options as JSTransformerOptions,
TransformOptions,
} from '../JSTransformer/worker/worker';
import type {Reporter} from '../lib/reporting';
import type GlobalTransformCache from '../lib/GlobalTransformCache';

Просмотреть файл

@ -8,13 +8,14 @@
*
* @flow
*/
/**
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*
* Based on the Base 64 VLQ implementation in Closure Compiler:
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
* https://git.io/vymuA
*
* Copyright 2011 The Closure Compiler Authors. All rights reserved.
* Redistribution and use in source and binary forms, with or without
@ -107,7 +108,8 @@ function toVLQSigned(value) {
* V8 OPTIMIZATION!
*/
function encode(value: number, buffer: Buffer, position: number): number {
let digit, vlq = toVLQSigned(value);
let vlq = toVLQSigned(value);
let digit;
do {
digit = vlq & VLQ_BASE_MASK;
vlq >>>= VLQ_BASE_SHIFT;

Просмотреть файл

@ -8,6 +8,8 @@
*/
'use strict';
/* eslint-disable max-len */
jest.disableAutomock();
const inline = require('../inline');
const {transform, transformFromAst} = require('babel-core');
@ -205,7 +207,9 @@ describe('inline constants', () => {
var b = a.ReactNative.Platform.select({});
}`;
const {ast} = inline('arbitrary.js', {code}, {platform: 'ios'});
expect(toString(ast)).toEqual(normalize(code.replace(/ReactNative\.Platform\.select[^;]+/, '1')));
expect(toString(ast)).toEqual(
normalize(code.replace(/ReactNative\.Platform\.select[^;]+/, '1')),
);
});
it('replaces React.Platform.select in the code if React is a top level import', () => {
@ -237,7 +241,9 @@ describe('inline constants', () => {
var b = a.ReactNative.Platform.select;
}`;
const {ast} = inline('arbitrary.js', {code}, {platform: 'android'});
expect(toString(ast)).toEqual(normalize(code.replace(/ReactNative.Platform\.select[^;]+/, '2')));
expect(toString(ast)).toEqual(
normalize(code.replace(/ReactNative.Platform\.select[^;]+/, '2')),
);
});
it('replaces require("react-native").Platform.select in the code', () => {
@ -269,18 +275,6 @@ describe('inline constants', () => {
normalize(code.replace(/process\.env\.NODE_ENV/, '"production"')));
});
it('replaces process.env.NODE_ENV in the code', () => {
const code = `function a() {
if (process.env.NODE_ENV === 'production') {
return require('Prod');
}
return require('Dev');
}`;
const {ast} = inline('arbitrary.js', {code}, {dev: true});
expect(toString(ast)).toEqual(
normalize(code.replace(/process\.env\.NODE_ENV/, '"development"')));
});
it('accepts an AST as input', function() {
const code = 'function ifDev(a,b){return __DEV__?a:b;}';
const {ast} = inline('arbitrary.hs', {ast: toAst(code)}, {dev: false});

Просмотреть файл

@ -33,7 +33,12 @@ function extractDependencies(code: string) {
const node = path.node;
const callee = node.callee;
const arg = node.arguments[0];
if (callee.type !== 'Identifier' || callee.name !== 'require' || !arg || arg.type !== 'StringLiteral') {
if (
callee.type !== 'Identifier' ||
callee.name !== 'require' ||
!arg ||
arg.type !== 'StringLiteral'
) {
return;
}
dependencyOffsets.push(arg.start);

Просмотреть файл

@ -208,50 +208,52 @@ describe('Graph:', () => {
});
});
it('calls back with an array of modules in depth-first traversal order, regardless of the order of resolution', done => {
load.stub.reset();
resolve.stub.reset();
it('resolves modules in depth-first traversal order, regardless of the order of resolution',
done => {
load.stub.reset();
resolve.stub.reset();
const ids = [
'a',
'b',
'c', 'd',
'e',
'f', 'g',
'h',
];
ids.forEach(id => {
const path = idToPath(id);
resolve.stub.withArgs(id).yields(null, path);
load.stub.withArgs(path).yields(null, createFile(id), []);
});
load.stub.withArgs(idToPath('a')).yields(null, createFile('a'), ['b', 'e', 'h']);
load.stub.withArgs(idToPath('b')).yields(null, createFile('b'), ['c', 'd']);
load.stub.withArgs(idToPath('e')).yields(null, createFile('e'), ['f', 'g']);
const ids = [
'a',
'b',
'c', 'd',
'e',
'f', 'g',
'h',
];
ids.forEach(id => {
const path = idToPath(id);
resolve.stub.withArgs(id).yields(null, path);
load.stub.withArgs(path).yields(null, createFile(id), []);
});
load.stub.withArgs(idToPath('a')).yields(null, createFile('a'), ['b', 'e', 'h']);
load.stub.withArgs(idToPath('b')).yields(null, createFile('b'), ['c', 'd']);
load.stub.withArgs(idToPath('e')).yields(null, createFile('e'), ['f', 'g']);
// load certain ids later
['b', 'e', 'h'].forEach(id => resolve.stub.withArgs(id).resetBehavior());
resolve.stub.withArgs('h').func = (a, b, c, d, callback) => {
callback(null, idToPath('h'));
['e', 'b'].forEach(
id => resolve.stub.withArgs(id).yield(null, idToPath(id)));
};
// load certain ids later
['b', 'e', 'h'].forEach(id => resolve.stub.withArgs(id).resetBehavior());
resolve.stub.withArgs('h').func = (a, b, c, d, callback) => {
callback(null, idToPath('h'));
['e', 'b'].forEach(
id => resolve.stub.withArgs(id).yield(null, idToPath(id)));
};
graph(['a'], anyPlatform, noOpts, (error, result) => {
expect(error).toEqual(null);
expect(result.modules).toEqual([
createModule('a', ['b', 'e', 'h']),
createModule('b', ['c', 'd']),
createModule('c'),
createModule('d'),
createModule('e', ['f', 'g']),
createModule('f'),
createModule('g'),
createModule('h'),
]);
done();
});
});
graph(['a'], anyPlatform, noOpts, (error, result) => {
expect(error).toEqual(null);
expect(result.modules).toEqual([
createModule('a', ['b', 'e', 'h']),
createModule('b', ['c', 'd']),
createModule('c'),
createModule('d'),
createModule('e', ['f', 'g']),
createModule('f'),
createModule('g'),
createModule('h'),
]);
done();
});
},
);
it('calls back with the resolved modules of the entry points', done => {
load.stub.reset();
@ -274,7 +276,7 @@ describe('Graph:', () => {
});
});
it('calls back with the resolved modules of the entry points if one entry point is a dependency of another', done => {
it('resolves modules for all entry points correctly if one is a dependency of another', done => {
load.stub.reset();
resolve.stub.reset();

Просмотреть файл

@ -25,7 +25,9 @@ module.exports = class HasteFS {
}
closest(path: string, fileName: string): ?string {
let {dir, root} = parse(path);
const parsedPath = parse(path);
const root = parsedPath.root;
let dir = parsedPath.dir;
do {
const candidate = join(dir, fileName);
if (this.files.has(candidate)) {
@ -63,7 +65,9 @@ module.exports = class HasteFS {
function buildDirectorySet(files) {
const directories = new Set();
files.forEach(path => {
let {dir, root} = parse(path);
const parsedPath = parse(path);
const root = parsedPath.root;
let dir = parsedPath.dir;
while (dir !== '.' && dir !== root && !directories.has(dir)) {
directories.add(dir);
dir = dirname(dir);

Просмотреть файл

@ -63,27 +63,29 @@ describe('dependency collection from ASTs:', () => {
.toEqual(any(String));
});
it('replaces all required module ID strings with array lookups and keeps the ID as second argument', () => {
const ast = astFromCode(`
const a = require('b/lib/a');
const b = require(123);
exports.do = () => require("do");
if (!something) {
require("setup/something");
}
`);
it('replaces all required module ID strings with array lookups, keeps the ID as second argument',
() => {
const ast = astFromCode(`
const a = require('b/lib/a');
const b = require(123);
exports.do = () => require("do");
if (!something) {
require("setup/something");
}
`);
const {dependencyMapName} = collectDependencies(ast);
const {dependencyMapName} = collectDependencies(ast);
expect(codeFromAst(ast)).toEqual(comparableCode(`
const a = require(${dependencyMapName}[0], 'b/lib/a');
const b = require(123);
exports.do = () => require(${dependencyMapName}[1], "do");
if (!something) {
require(${dependencyMapName}[2], "setup/something");
}
`));
});
expect(codeFromAst(ast)).toEqual(comparableCode(`
const a = require(${dependencyMapName}[0], 'b/lib/a');
const b = require(123);
exports.do = () => require(${dependencyMapName}[1], "do");
if (!something) {
require(${dependencyMapName}[2], "setup/something");
}
`));
},
);
});
describe('Dependency collection from optimized ASTs:', () => {

Просмотреть файл

@ -94,4 +94,5 @@ function findLast(code, needle) {
return {line: line + 1, column};
}
}
return null;
}

Просмотреть файл

@ -19,8 +19,6 @@ const {parse} = require('babylon');
const generate = require('babel-generator').default;
const {traverse} = require('babel-core');
const {any, objectContaining} = jasmine;
describe('transforming JS modules:', () => {
const filename = 'arbitrary';
@ -47,7 +45,7 @@ describe('transforming JS modules:', () => {
it('passes through file name and code', done => {
transformModule(sourceCode, options(), (error, result) => {
expect(result).toEqual(objectContaining({
expect(result).toEqual(expect.objectContaining({
code: sourceCode,
file: filename,
}));
@ -59,36 +57,39 @@ describe('transforming JS modules:', () => {
const hasteID = 'TheModule';
const codeWithHasteID = `/** @providesModule ${hasteID} */`;
transformModule(codeWithHasteID, options(), (error, result) => {
expect(result).toEqual(objectContaining({hasteID}));
expect(result).toEqual(expect.objectContaining({hasteID}));
done();
});
});
it('sets `type` to `"module"` by default', done => {
transformModule(sourceCode, options(), (error, result) => {
expect(result).toEqual(objectContaining({type: 'module'}));
expect(result).toEqual(expect.objectContaining({type: 'module'}));
done();
});
});
it('sets `type` to `"script"` if the input is a polyfill', done => {
transformModule(sourceCode, {...options(), polyfill: true}, (error, result) => {
expect(result).toEqual(objectContaining({type: 'script'}));
expect(result).toEqual(expect.objectContaining({type: 'script'}));
done();
});
});
it('calls the passed-in transform function with code, file name, and options for all passed in variants', done => {
const variants = {dev: {dev: true}, prod: {dev: false}};
it('calls the passed-in transform function with code, file name, and options ' +
'for all passed in variants',
done => {
const variants = {dev: {dev: true}, prod: {dev: false}};
transformModule(sourceCode, options(variants), () => {
expect(transformer.transform)
.toBeCalledWith(sourceCode, filename, variants.dev);
expect(transformer.transform)
.toBeCalledWith(sourceCode, filename, variants.prod);
done();
});
});
transformModule(sourceCode, options(variants), () => {
expect(transformer.transform)
.toBeCalledWith(sourceCode, filename, variants.dev);
expect(transformer.transform)
.toBeCalledWith(sourceCode, filename, variants.prod);
done();
});
},
);
it('calls back with any error yielded by the transform function', done => {
const error = new Error();
@ -114,7 +115,7 @@ describe('transforming JS modules:', () => {
});
});
it('wraps the code produced by the transform function into an immediately invoked function expression for polyfills', done => {
it('wraps the code produced by the transform function into an IIFE for polyfills', done => {
transformModule(sourceCode, {...options(), polyfill: true}, (error, result) => {
expect(error).toEqual(null);
@ -131,20 +132,21 @@ describe('transforming JS modules:', () => {
const column = code.indexOf('code');
const consumer = new SourceMapConsumer(map);
expect(consumer.originalPositionFor({line: 1, column}))
.toEqual(objectContaining({line: 1, column: sourceCode.indexOf('code')}));
.toEqual(expect.objectContaining({line: 1, column: sourceCode.indexOf('code')}));
done();
});
});
it('extracts dependencies (require calls)', done => {
const dep1 = 'foo', dep2 = 'bar';
const dep1 = 'foo';
const dep2 = 'bar';
const code = `require('${dep1}'),require('${dep2}')`;
const {body} = parse(code).program;
transformer.transform.stub.returns(transformResult(body));
transformModule(code, options(), (error, result) => {
expect(result.transformed.default)
.toEqual(objectContaining({dependencies: [dep1, dep2]}));
.toEqual(expect.objectContaining({dependencies: [dep1, dep2]}));
done();
});
});
@ -190,7 +192,7 @@ describe('transforming JS modules:', () => {
it('does not create source maps for JSON files', done => {
transformModule('{}', {...options(), filename: 'some.json'}, (error, result) => {
expect(result.transformed.default)
.toEqual(objectContaining({map: null}));
.toEqual(expect.objectContaining({map: null}));
done();
});
});

Просмотреть файл

@ -44,7 +44,8 @@ function transformModule(
callback: Callback<TransformedFile>,
): void {
if (options.filename.endsWith('.json')) {
return transformJSON(code, options, callback);
transformJSON(code, options, callback);
return;
}
const {filename, transformer, variants = defaultVariants} = options;
@ -86,6 +87,7 @@ function transformModule(
type: options.polyfill ? 'script' : 'module',
});
});
return;
}
function transformJSON(json, options, callback) {

Просмотреть файл

@ -237,40 +237,6 @@ describe('Resolver', function() {
});
});
it('should get dependencies with polyfills', function() {
var module = createModule('index');
var deps = [module];
var depResolver = new Resolver({
projectRoot: '/root',
});
DependencyGraph.prototype.getDependencies.mockImplementation(function() {
return Promise.resolve(new ResolutionResponseMock({
dependencies: deps,
mainModuleId: 'index',
}));
});
const polyfill = {};
DependencyGraph.prototype.createPolyfill.mockReturnValueOnce(polyfill);
return depResolver
.getDependencies(
'/root/index.js',
{dev: true},
undefined,
undefined,
createGetModuleId()
).then(function(result) {
expect(result.mainModuleId).toEqual('index');
expect(DependencyGraph.mock.instances[0].getDependencies)
.toBeCalledWith({entryPath: '/root/index.js', recursive: true});
expect(result.dependencies[0]).toBe(polyfill);
expect(result.dependencies[result.dependencies.length - 1])
.toBe(module);
});
});
it('should pass in more polyfills', function() {
var module = createModule('index');
var deps = [module];
@ -296,7 +262,9 @@ describe('Resolver', function() {
createGetModuleId()
).then(result => {
expect(result.mainModuleId).toEqual('index');
expect(DependencyGraph.prototype.createPolyfill.mock.calls[result.dependencies.length - 2]).toEqual([
const calls =
DependencyGraph.prototype.createPolyfill.mock.calls[result.dependencies.length - 2];
expect(calls).toEqual([
{file: 'some module',
id: 'some module',
dependencies: [
@ -444,7 +412,8 @@ describe('Resolver', function() {
expect(processedCode).toEqual([
'(function(global) {',
'global.fetch = () => 1;',
"\n})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);",
'\n})' +
"(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);",
].join(''));
});
});

Просмотреть файл

@ -76,7 +76,8 @@ class Resolver {
},
platforms: new Set(opts.platforms),
preferNativePlatform: true,
providesModuleNodeModules: opts.providesModuleNodeModules || defaults.providesModuleNodeModules,
providesModuleNodeModules:
opts.providesModuleNodeModules || defaults.providesModuleNodeModules,
reporter: opts.reporter,
resetCache: opts.resetCache,
roots: opts.projectRoots,
@ -261,7 +262,7 @@ function defineModuleCode(moduleName, code, verboseName = '', dev = true) {
].join('');
}
function definePolyfillCode(code,) {
function definePolyfillCode(code) {
return [
'(function(global) {',
code,

Просмотреть файл

@ -27,6 +27,7 @@ if (Number.MIN_SAFE_INTEGER === undefined) {
});
}
if (!Number.isNaN) {
// eslint-disable-next-line max-len
// https://github.com/dherman/tc39-codex-wiki/blob/master/data/es6/number/index.md#polyfill-for-numberisnan
const globalIsNaN = global.isNaN;
Object.defineProperty(Number, 'isNaN', {

Просмотреть файл

@ -52,6 +52,7 @@ const ErrorUtils = {
} finally {
_inGuard--;
}
return null;
},
applyWithGuardIfNeeded(fun, context, args) {
if (ErrorUtils.inGuard()) {
@ -59,6 +60,7 @@ const ErrorUtils = {
} else {
ErrorUtils.applyWithGuard(fun, context, args);
}
return null;
},
inGuard() {
return _inGuard;

Просмотреть файл

@ -43,7 +43,8 @@ const {
} = require('../Logger');
function debounceAndBatch(fn, delay) {
let timeout, args = [];
let args = [];
let timeout;
return value => {
args.push(value);
clearTimeout(timeout);
@ -957,7 +958,8 @@ class Server {
'entryModuleOnly',
false,
),
generateSourceMaps: minify || !dev || this._getBoolOptionFromQuery(urlObj.query, 'babelSourcemap', false),
generateSourceMaps:
minify || !dev || this._getBoolOptionFromQuery(urlObj.query, 'babelSourcemap', false),
assetPlugins,
};
}

Просмотреть файл

@ -17,11 +17,11 @@ import type {MixedSourceMap} from './SourceMap';
function relativizeSourceMapInternal(sourceMap: any, sourcesRoot: string) {
if (sourceMap.sections) {
for (var i = 0; i < sourceMap.sections.length; i++) {
for (let i = 0; i < sourceMap.sections.length; i++) {
relativizeSourceMapInternal(sourceMap.sections[i].map, sourcesRoot);
}
} else {
for (var i = 0; i < sourceMap.sources.length; i++) {
for (let i = 0; i < sourceMap.sources.length; i++) {
sourceMap.sources[i] = path.relative(sourcesRoot, sourceMap.sources[i]);
}
}

Просмотреть файл

@ -87,6 +87,7 @@ class HasteMap extends EventEmitter {
return this._processHasteModule(absPath, invalidated);
}
}
return null;
});
}

Просмотреть файл

@ -37,7 +37,7 @@ fs.realpath.mockImplementation((filepath, callback) => {
if (node && typeof node === 'object' && node.SYMLINK != null) {
return callback(null, node.SYMLINK);
}
callback(null, filepath);
return callback(null, filepath);
});
fs.readdirSync.mockImplementation(filepath => Object.keys(getToNode(filepath)));
@ -58,7 +58,7 @@ fs.readdir.mockImplementation((filepath, callback) => {
return callback(new Error(filepath + ' is not a directory.'));
}
callback(null, Object.keys(node));
return callback(null, Object.keys(node));
});
fs.readFile.mockImplementation(function(filepath, encoding, callback) {
@ -76,9 +76,9 @@ fs.readFile.mockImplementation(function(filepath, encoding, callback) {
callback(new Error('Error readFile a dir: ' + filepath));
}
if (node == null) {
callback(Error('No such file: ' + filepath));
return callback(Error('No such file: ' + filepath));
} else {
callback(null, node);
return callback(null, node);
}
} catch (e) {
return callback(e);

Просмотреть файл

@ -748,7 +748,7 @@ describe('DependencyGraph', function() {
});
});
it('should work with packages', function() {
it('should work with packages with a trailing slash', function() {
var root = '/root';
setMockFileSystem({
'root': {

Просмотреть файл

@ -130,7 +130,9 @@ class DependencyGraph extends EventEmitter {
moduleOptions: this._opts.moduleOptions,
reporter: this._opts.reporter,
getClosestPackage: filePath => {
let {dir, root} = path.parse(filePath);
const parsedPath = path.parse(filePath);
const root = parsedPath.root;
let dir = parsedPath.dir;
do {
const candidate = path.join(dir, 'package.json');
if (this._hasteFS.exists(candidate)) {

Просмотреть файл

@ -35,7 +35,7 @@ const getBabelRC = (function() {
return babelRC;
}
babelRC = { plugins: [] }; // empty babelrc
babelRC = {plugins: []}; // empty babelrc
// Let's look for the .babelrc in the first project root.
// In the future let's look into adding a command line option to specify
@ -54,7 +54,7 @@ const getBabelRC = (function() {
);
// Require the babel-preset's listed in the default babel config
babelRC.presets = babelRC.presets.map((preset) => require('babel-preset-' + preset));
babelRC.presets = babelRC.presets.map(preset => require('babel-preset-' + preset));
babelRC.plugins = resolvePlugins(babelRC.plugins);
} else {
// if we find a .babelrc file we tell babel to use it