metro-bundler: @format lib/

Reviewed By: cpojer

Differential Revision: D5493458

fbshipit-source-id: 05ac2895125b1419996a66f3ef155bc2cec11c02
This commit is contained in:
Jean Lauliac 2017-07-26 12:18:07 -07:00 committed by Facebook Github Bot
parent 521e25bded
commit 14b88b6ad4
17 changed files with 361 additions and 222 deletions

View File

@ -7,13 +7,16 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
const invariant = require('fbjs/lib/invariant');
type ProcessBatch<TItem, TResult> = (batch: Array<TItem>) => Promise<Array<TResult>>;
type ProcessBatch<TItem, TResult> = (
batch: Array<TItem>,
) => Promise<Array<TResult>>;
type BatchProcessorOptions = {
maximumDelayMs: number,
@ -35,14 +38,16 @@ type QueueItem<TItem, TResult> = {
* processing right away.
*/
class BatchProcessor<TItem, TResult> {
_currentProcessCount: number;
_options: BatchProcessorOptions;
_processBatch: ProcessBatch<TItem, TResult>;
_queue: Array<QueueItem<TItem, TResult>>;
_timeoutHandle: ?number;
constructor(options: BatchProcessorOptions, processBatch: ProcessBatch<TItem, TResult>) {
constructor(
options: BatchProcessorOptions,
processBatch: ProcessBatch<TItem, TResult>,
) {
this._options = options;
this._processBatch = processBatch;
this._queue = [];
@ -56,7 +61,10 @@ class BatchProcessor<TItem, TResult> {
this._processQueueOnceReady();
}
_onBatchResults(jobs: Array<QueueItem<TItem, TResult>>, results: Array<TResult>) {
_onBatchResults(
jobs: Array<QueueItem<TItem, TResult>>,
results: Array<TResult>,
) {
invariant(results.length === jobs.length, 'Not enough results returned.');
for (let i = 0; i < jobs.length; ++i) {
jobs[i].resolve(results[i]);
@ -104,7 +112,6 @@ class BatchProcessor<TItem, TResult> {
this._processQueueOnceReady();
});
}
}
module.exports = BatchProcessor;

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
@ -76,7 +77,6 @@ type URI = string;
* ensures we do a single request at a time to avoid pressuring the I/O.
*/
class KeyURIFetcher {
_batchProcessor: BatchProcessor<string, ?URI>;
_fetchResultURIs: FetchResultURIs;
@ -96,24 +96,27 @@ class KeyURIFetcher {
constructor(fetchResultURIs: FetchResultURIs) {
this._fetchResultURIs = fetchResultURIs;
this._batchProcessor = new BatchProcessor({
maximumDelayMs: 10,
maximumItems: 500,
concurrency: 2,
}, this._processKeys.bind(this));
this._batchProcessor = new BatchProcessor(
{
maximumDelayMs: 10,
maximumItems: 500,
concurrency: 2,
},
this._processKeys.bind(this),
);
}
}
type KeyedResult = {key: string, result: CachedResult};
class KeyResultStore {
_storeResults: StoreResults;
_batchProcessor: BatchProcessor<KeyedResult, void>;
async _processResults(keyResults: Array<KeyedResult>): Promise<Array<void>> {
const resultsByKey = new Map(keyResults.map(pair => [pair.key, pair.result]));
const resultsByKey = new Map(
keyResults.map(pair => [pair.key, pair.result]),
);
await this._storeResults(resultsByKey);
return new Array(keyResults.length);
}
@ -124,16 +127,22 @@ class KeyResultStore {
constructor(storeResults: StoreResults) {
this._storeResults = storeResults;
this._batchProcessor = new BatchProcessor({
maximumDelayMs: 1000,
maximumItems: 100,
concurrency: 10,
}, this._processResults.bind(this));
this._batchProcessor = new BatchProcessor(
{
maximumDelayMs: 1000,
maximumItems: 100,
concurrency: 10,
},
this._processResults.bind(this),
);
}
}
export type TransformProfile = {+dev: boolean, +minify: boolean, +platform: ?string};
export type TransformProfile = {
+dev: boolean,
+minify: boolean,
+platform: ?string,
};
function profileKey({dev, minify, platform}: TransformProfile): string {
return jsonStableStringify({dev, minify, platform});
@ -157,14 +166,14 @@ class TransformProfileSet {
}
type FetchFailedDetails =
{
+statusCode: number,
+statusText: string,
+type: 'unhandled_http_status',
+uri: string,
} |
{+type: 'invalid_data'} |
{+type: 'invalid_key_data', key: string};
| {
+statusCode: number,
+statusText: string,
+type: 'unhandled_http_status',
+uri: string,
}
| {+type: 'invalid_data'}
| {+type: 'invalid_key_data', key: string};
class FetchFailedError extends Error {
/** Separate object for details allows us to have a type union. */
@ -179,8 +188,8 @@ class FetchFailedError extends Error {
if (details.type === 'unhandled_http_status') {
return (
`Unexpected HTTP status: ${details.statusCode} ` +
JSON.stringify(details.statusText) +
` while fetching \`${details.uri}\``
JSON.stringify(details.statusText) +
` while fetching \`${details.uri}\``
);
}
if (details.type === 'invalid_key_data') {
@ -210,7 +219,6 @@ function validateCachedResult(cachedResult: mixed): ?CachedResult {
}
class URIBasedGlobalTransformCache {
_fetcher: KeyURIFetcher;
_fetchResultFromURI: FetchResultFromURI;
_profileSet: TransformProfileSet;
@ -249,7 +257,9 @@ class URIBasedGlobalTransformCache {
keyOf(props: FetchProps) {
const hash = crypto.createHash('sha1');
const {sourceCode, localPath, transformOptions} = props;
hash.update(this._optionsHasher.getTransformWorkerOptionsDigest(transformOptions));
hash.update(
this._optionsHasher.getTransformWorkerOptionsDigest(transformOptions),
);
const cacheKey = props.getTransformCacheKey(transformOptions);
hash.update(JSON.stringify(cacheKey));
hash.update(JSON.stringify(localPath));
@ -287,7 +297,9 @@ class URIBasedGlobalTransformCache {
* waiting a little time before retring if experience shows it's useful.
*/
static _fetchResultFromURIWithRetry(uri: string): Promise<CachedResult> {
return URIBasedGlobalTransformCache._fetchResultFromURI(uri).catch(error => {
return URIBasedGlobalTransformCache._fetchResultFromURI(
uri,
).catch(error => {
if (!URIBasedGlobalTransformCache.shouldRetryAfterThatError(error)) {
throw error;
}
@ -311,11 +323,10 @@ class URIBasedGlobalTransformCache {
*/
static shouldRetryAfterThatError(error: mixed): boolean {
return (
error instanceof FetchError && error.type === 'request-timeout' || (
error instanceof FetchFailedError &&
(error instanceof FetchError && error.type === 'request-timeout') ||
(error instanceof FetchFailedError &&
error.details.type === 'unhandled_http_status' &&
(error.details.statusCode === 503 || error.details.statusCode === 502)
)
(error.details.statusCode === 503 || error.details.statusCode === 502))
);
}
@ -340,11 +351,12 @@ class URIBasedGlobalTransformCache {
this._store.store(this.keyOf(props), result);
}
}
}
URIBasedGlobalTransformCache.fetchResultFromURI =
throat(500, URIBasedGlobalTransformCache._fetchResultFromURIWithRetry);
URIBasedGlobalTransformCache.fetchResultFromURI = throat(
500,
URIBasedGlobalTransformCache._fetchResultFromURIWithRetry,
);
class OptionsHasher {
_rootPath: string;
@ -383,15 +395,20 @@ class OptionsHasher {
* many different fields including the optional Babel fields, and some serious
* cleanup will be necessary to enable rock-solid typing.
*/
hashTransformWorkerOptions(hash: crypto$Hash, options: TransformWorkerOptions): crypto$Hash {
hashTransformWorkerOptions(
hash: crypto$Hash,
options: TransformWorkerOptions,
): crypto$Hash {
const {dev, minify, platform, transform, ...unknowns} = options;
const unknownKeys = Object.keys(unknowns);
if (unknownKeys.length > 0) {
const message = `these worker option fields are unknown: ${JSON.stringify(unknownKeys)}`;
const message = `these worker option fields are unknown: ${JSON.stringify(
unknownKeys,
)}`;
throw new CannotHashOptionsError(message);
}
// eslint-disable-next-line no-undef, no-bitwise
hash.update(new Buffer([+dev | +minify << 1]));
hash.update(new Buffer([+dev | (+minify << 1)]));
hash.update(JSON.stringify(platform));
return this.hashTransformOptions(hash, transform);
}
@ -404,25 +421,45 @@ class OptionsHasher {
* of the cache key as they should not affect the transformation of a single
* particular file.
*/
hashTransformOptions(hash: crypto$Hash, options: TransformOptionsStrict): crypto$Hash {
hashTransformOptions(
hash: crypto$Hash,
options: TransformOptionsStrict,
): crypto$Hash {
const {
generateSourceMaps, dev, hot, inlineRequires, platform, projectRoot,
generateSourceMaps,
dev,
hot,
inlineRequires,
platform,
projectRoot,
...unknowns
} = options;
const unknownKeys = Object.keys(unknowns);
if (unknownKeys.length > 0) {
const message = `these transform option fields are unknown: ${JSON.stringify(unknownKeys)}`;
const message = `these transform option fields are unknown: ${JSON.stringify(
unknownKeys,
)}`;
throw new CannotHashOptionsError(message);
}
hash.update(new Buffer([
// eslint-disable-next-line no-bitwise
+dev | +generateSourceMaps << 1 | +hot << 2 | +!!inlineRequires << 3,
]));
hash.update(
new Buffer([
// eslint-disable-next-line no-bitwise
+dev |
// eslint-disable-next-line no-bitwise
(+generateSourceMaps << 1) |
// eslint-disable-next-line no-bitwise
(+hot << 2) |
// eslint-disable-next-line no-bitwise
(+!!inlineRequires << 3),
]),
);
hash.update(JSON.stringify(platform));
let blacklistWithLocalPaths = [];
if (typeof inlineRequires === 'object') {
blacklistWithLocalPaths = this.pathsToLocal(Object.keys(inlineRequires.blacklist));
blacklistWithLocalPaths = this.pathsToLocal(
Object.keys(inlineRequires.blacklist),
);
}
const localProjectRoot = this.toLocalPath(projectRoot);
const optionTuple = [blacklistWithLocalPaths, localProjectRoot];

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
@ -14,7 +15,6 @@
import {Writable} from 'stream';
class JsonReporter<TEvent: {}> {
_stream: Writable;
constructor(stream: Writable) {
@ -37,7 +37,6 @@ class JsonReporter<TEvent: {}> {
}
this._stream.write(JSON.stringify(event) + '\n');
}
}
module.exports = JsonReporter;

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
@ -24,7 +25,6 @@ type Metadata = {
};
class ModuleTransport {
name: string;
id: number;
code: string;
@ -67,7 +67,6 @@ class ModuleTransport {
Object.freeze(this);
}
}
module.exports = ModuleTransport;

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
@ -32,7 +33,7 @@ export type FBIndexMap = IndexMap & FBExtensions;
export type SourceMap = IndexMap | MappingsMap;
export type FBSourceMap = FBIndexMap | (MappingsMap & FBExtensions);
function isMappingsMap(map: SourceMap)/*: %checks*/ {
function isMappingsMap(map: SourceMap): %checks {
return map.mappings !== undefined;
}

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
@ -49,12 +50,14 @@ function getProgressBar(ratio: number, length: number) {
);
}
export type TerminalReportableEvent = ReportableEvent | {
buildID: string,
type: 'bundle_transform_progressed_throttled',
transformedFileCount: number,
totalFileCount: number,
};
export type TerminalReportableEvent =
| ReportableEvent
| {
buildID: string,
type: 'bundle_transform_progressed_throttled',
transformedFileCount: number,
totalFileCount: number,
};
type BuildPhase = 'in_progress' | 'done' | 'failed';
@ -63,7 +66,6 @@ type BuildPhase = 'in_progress' | 'done' | 'failed';
* This implements the `Reporter` interface from the './reporting' module.
*/
class TerminalReporter {
/**
* The bundle builds for which we are actively maintaining the status on the
* terminal, ie. showing a progress bar. There can be several bundles being
@ -115,7 +117,7 @@ class TerminalReporter {
(100 * ratio).toFixed(1),
transformedFileCount,
totalFileCount,
phase === 'done' ? ', done.' : (phase === 'failed' ? ', failed.' : ''),
phase === 'done' ? ', done.' : phase === 'failed' ? ', failed.' : '',
);
}
@ -142,11 +144,14 @@ class TerminalReporter {
_logBundleBuildDone(buildID: string) {
const progress = this._activeBundles.get(buildID);
if (progress != null) {
const msg = this._getBundleStatusMessage({
...progress,
ratio: 1,
transformedFileCount: progress.totalFileCount,
}, 'done');
const msg = this._getBundleStatusMessage(
{
...progress,
ratio: 1,
transformedFileCount: progress.totalFileCount,
},
'done',
);
this.terminal.log(msg);
}
}
@ -166,21 +171,21 @@ class TerminalReporter {
port +
'.\n\n' +
'Keep this packager running while developing on any JS projects. ' +
'Feel free to close this tab and run your own packager instance if you ' +
'prefer.\n\n' +
'Feel free to close this tab and run your own packager instance ' +
'if you prefer.\n\n' +
'https://github.com/facebook/react-native',
{
marginLeft: 1,
marginRight: 1,
paddingBottom: 1,
}
)
},
),
);
this.terminal.log(
'Looking for JS files in\n ',
chalk.dim(projectRoots.join('\n ')),
'\n'
'\n',
);
}
@ -188,9 +193,11 @@ class TerminalReporter {
if (error.code === 'EADDRINUSE') {
this.terminal.log(
chalk.bgRed.bold(' ERROR '),
chalk.red("Packager can't listen on port", chalk.bold(port))
chalk.red("Packager can't listen on port", chalk.bold(port)),
);
this.terminal.log(
'Most likely another process is already using this port',
);
this.terminal.log('Most likely another process is already using this port');
this.terminal.log('Run the following command to find out which process:');
this.terminal.log('\n ', chalk.bold('lsof -i :' + port), '\n');
this.terminal.log('Then, you can either shut down the other process:');
@ -258,9 +265,9 @@ class TerminalReporter {
const he = error.hasteError;
const message =
'ambiguous resolution: module `' +
`${error.fromModulePath}\` tries to require \`${he.hasteName}\`, but ` +
`there are several files providing this module. You can delete or ` +
'fix them: \n\n' +
`${error.fromModulePath}\` tries to require \`${he.hasteName}\`, ` +
`but there are several files providing this module. You can delete ` +
'or fix them: \n\n' +
Object.keys(he.duplicatesSet)
.sort()
.map(dupFilePath => ` * \`${dupFilePath}\`\n`)
@ -269,10 +276,11 @@ class TerminalReporter {
return;
}
let message = (error.snippet == null && error.stack != null)
? error.stack
//$FlowFixMe T19379628
: error.message;
let message =
error.snippet == null && error.stack != null
? error.stack
: //$FlowFixMe T19379628
error.message;
//$FlowFixMe T19379628
if (error.filename && !message.includes(error.filename)) {
//$FlowFixMe T19379628
@ -305,13 +313,15 @@ class TerminalReporter {
* we know the `totalCount` is going to progressively increase as well. We
* also prevent the ratio from going backwards.
*/
_updateBundleProgress(
{buildID, transformedFileCount, totalFileCount}: {
buildID: string,
transformedFileCount: number,
totalFileCount: number,
},
) {
_updateBundleProgress({
buildID,
transformedFileCount,
totalFileCount,
}: {
buildID: string,
transformedFileCount: number,
totalFileCount: number,
}) {
const currentProgress = this._activeBundles.get(buildID);
if (currentProgress == null) {
return;
@ -377,12 +387,14 @@ class TerminalReporter {
* different callsites overriding each other status messages.
*/
_getStatusMessage(): string {
return [
this._getDepGraphStatusMessage(),
].concat(Array.from(this._activeBundles.entries()).map(
([_, progress]) =>
this._getBundleStatusMessage(progress, 'in_progress'),
)).filter(str => str != null).join('\n');
return [this._getDepGraphStatusMessage()]
.concat(
Array.from(this._activeBundles.entries()).map(([_, progress]) =>
this._getBundleStatusMessage(progress, 'in_progress'),
),
)
.filter(str => str != null)
.join('\n');
}
/**
@ -394,7 +406,6 @@ class TerminalReporter {
this._updateState(event);
this.terminal.status(this._getStatusMessage());
}
}
module.exports = TerminalReporter;

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';

View File

@ -5,6 +5,8 @@
* 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.
*
* @format
*/
'use strict';
@ -15,14 +17,22 @@ const jsonStableStringify = require('json-stable-stringify');
const transformCache = new Map();
const transformCacheKeyOf = props =>
props.filePath + '-' + crypto.createHash('md5')
props.filePath +
'-' +
crypto
.createHash('md5')
.update(props.sourceCode)
.update(props.getTransformCacheKey(props.sourceCode, props.filePath, props.transformOptions))
.update(
props.getTransformCacheKey(
props.sourceCode,
props.filePath,
props.transformOptions,
),
)
.update(jsonStableStringify(props.transformOptions || {}))
.digest('hex');
class TransformCacheMock {
constructor() {
this.mock = {
lastWrite: null,
@ -39,9 +49,11 @@ class TransformCacheMock {
}
readSync(props) {
return {result: transformCache.get(transformCacheKeyOf(props)), outdatedDependencies: []};
return {
result: transformCache.get(transformCacheKeyOf(props)),
outdatedDependencies: [],
};
}
}
module.exports = {mocked: () => new TransformCacheMock()};

View File

@ -5,7 +5,10 @@
* 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.
*
* @format
*/
'use strict';
module.exports = function(declared) {

View File

@ -5,6 +5,8 @@
* 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.
*
* @format
*/
'use strict';
@ -14,7 +16,6 @@ jest.useRealTimers();
const BatchProcessor = require('../BatchProcessor');
describe('BatchProcessor', () => {
const options = {
maximumDelayMs: 500,
maximumItems: 3,
@ -27,40 +28,50 @@ describe('BatchProcessor', () => {
const batches = [];
let concurrency = 0;
let maxConcurrency = 0;
const bp = new BatchProcessor(options, items => new Promise(resolve => {
++concurrency;
expect(concurrency).toBeLessThanOrEqual(options.concurrency);
maxConcurrency = Math.max(maxConcurrency, concurrency);
batches.push(items);
setTimeout(() => {
resolve(items.map(transform));
--concurrency;
}, 0);
}));
const bp = new BatchProcessor(
options,
items =>
new Promise(resolve => {
++concurrency;
expect(concurrency).toBeLessThanOrEqual(options.concurrency);
maxConcurrency = Math.max(maxConcurrency, concurrency);
batches.push(items);
setTimeout(() => {
resolve(items.map(transform));
--concurrency;
}, 0);
}),
);
const results = [];
await Promise.all(input.map(e => bp.queue(e).then(
res => results.push(res),
error => process.nextTick(() => { throw error; }),
)));
expect(batches).toEqual([
[1, 2, 3],
[4, 5, 6],
[7, 8],
]);
await Promise.all(
input.map(e =>
bp.queue(e).then(
res => results.push(res),
error =>
process.nextTick(() => {
throw error;
}),
),
),
);
expect(batches).toEqual([[1, 2, 3], [4, 5, 6], [7, 8]]);
expect(maxConcurrency).toEqual(options.concurrency);
expect(results).toEqual(input.map(transform));
});
it('report errors', async () => {
const error = new Error('oh noes');
const bp = new BatchProcessor(options, items => new Promise((_, reject) => {
setTimeout(reject.bind(null, error), 0);
}));
let receivedError;
await bp.queue('foo').catch(
err => { receivedError = err; },
const bp = new BatchProcessor(
options,
items =>
new Promise((_, reject) => {
setTimeout(reject.bind(null, error), 0);
}),
);
let receivedError;
await bp.queue('foo').catch(err => {
receivedError = err;
});
expect(receivedError).toBe(error);
});
});

View File

@ -5,6 +5,8 @@
* 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.
*
* @format
*/
'use strict';
@ -18,7 +20,9 @@ const {URIBasedGlobalTransformCache} = require('../GlobalTransformCache');
const FetchError = require('node-fetch/lib/fetch-error');
const path = require('path');
async function fetchResultURIs(keys: Array<string>): Promise<Map<string, string>> {
async function fetchResultURIs(
keys: Array<string>,
): Promise<Map<string, string>> {
return new Map(keys.map(key => [key, `http://globalcache.com/${key}`]));
}
@ -31,7 +35,6 @@ async function fetchResultFromURI(uri: string): Promise<?CachedResult> {
}
describe('GlobalTransformCache', () => {
it('fetches results', async () => {
const cache = new URIBasedGlobalTransformCache({
fetchResultFromURI,
@ -53,22 +56,24 @@ describe('GlobalTransformCache', () => {
projectRoot: path.join(__dirname, 'root'),
},
};
const result = await Promise.all([cache.fetch({
localPath: 'some/where/foo.js',
sourceCode: '/* beep */',
getTransformCacheKey: () => 'abcd',
transformOptions,
}), cache.fetch({
localPath: 'some/where/else/bar.js',
sourceCode: '/* boop */',
getTransformCacheKey: () => 'abcd',
transformOptions,
})]);
const result = await Promise.all([
cache.fetch({
localPath: 'some/where/foo.js',
sourceCode: '/* beep */',
getTransformCacheKey: () => 'abcd',
transformOptions,
}),
cache.fetch({
localPath: 'some/where/else/bar.js',
sourceCode: '/* boop */',
getTransformCacheKey: () => 'abcd',
transformOptions,
}),
]);
expect(result).toMatchSnapshot();
});
describe('fetchResultFromURI', () => {
const defaultFetchMockImpl = async uri => ({
status: 200,
json: async () => ({
@ -84,8 +89,9 @@ describe('GlobalTransformCache', () => {
it('fetches result', async () => {
mockFetch.mockImplementation(defaultFetchMockImpl);
const result = await URIBasedGlobalTransformCache
.fetchResultFromURI('http://globalcache.com/foo');
const result = await URIBasedGlobalTransformCache.fetchResultFromURI(
'http://globalcache.com/foo',
);
expect(result).toMatchSnapshot();
});
@ -94,11 +100,10 @@ describe('GlobalTransformCache', () => {
mockFetch.mockImplementation(defaultFetchMockImpl);
throw new FetchError('timeout!', 'request-timeout');
});
const result = await URIBasedGlobalTransformCache
.fetchResultFromURI('http://globalcache.com/foo');
const result = await URIBasedGlobalTransformCache.fetchResultFromURI(
'http://globalcache.com/foo',
);
expect(result).toMatchSnapshot();
});
});
});

View File

@ -5,6 +5,8 @@
* 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.
*
* @format
*/
'use strict';
@ -12,10 +14,13 @@
jest.mock('readline', () => ({
moveCursor: (stream, dx, dy) => {
const {cursor, columns} = stream;
stream.cursor = Math.max(cursor - cursor % columns, cursor + dx) + dy * columns;
stream.cursor =
Math.max(cursor - cursor % columns, cursor + dx) + dy * columns;
},
clearLine: (stream, dir) => {
if (dir !== 0) {throw new Error('unsupported');}
if (dir !== 0) {
throw new Error('unsupported');
}
const {cursor, columns} = stream;
const curLine = cursor - cursor % columns;
const nextLine = curLine + columns;
@ -26,7 +31,6 @@ jest.mock('readline', () => ({
}));
describe('Terminal', () => {
beforeEach(() => {
jest.resetModules();
});
@ -46,7 +50,7 @@ describe('Terminal', () => {
write(str) {
for (let i = 0; i < str.length; ++i) {
if (str[i] === '\n') {
this.cursor = this.cursor - (this.cursor % columns) + columns;
this.cursor = this.cursor - this.cursor % columns + columns;
} else {
this.buffer[this.cursor] = str[i];
++this.cursor;
@ -81,10 +85,14 @@ describe('Terminal', () => {
terminal.status('status2');
terminal.log('bar');
jest.runAllTimers();
expect(stream.buffer.join('').trim()).toEqual('foo bar status2');
expect(stream.buffer.join('').trim()).toEqual(
'foo bar status2',
);
terminal.log('beep');
jest.runAllTimers();
expect(stream.buffer.join('').trim()).toEqual('foo bar beep status2');
expect(stream.buffer.join('').trim()).toEqual(
'foo bar beep status2',
);
});
it('updates status when logging, multi-line', () => {
@ -93,8 +101,9 @@ describe('Terminal', () => {
terminal.status('status\nanother');
terminal.log('bar');
jest.runAllTimers();
expect(stream.buffer.join('').trim())
.toEqual('foo bar status another');
expect(stream.buffer.join('').trim()).toEqual(
'foo bar status another',
);
});
it('persists status', () => {
@ -106,5 +115,4 @@ describe('Terminal', () => {
jest.runAllTimers();
expect(stream.buffer.join('').trim()).toEqual('foo status bar');
});
});

View File

@ -5,6 +5,8 @@
* 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.
*
* @format
*/
'use strict';
@ -43,13 +45,14 @@ function cartesianProductOf(a1, a2) {
}
describe('TransformCaching.FileBasedCache', () => {
let transformCache;
beforeEach(() => {
jest.resetModules();
mockFS.clear();
transformCache = new (require('../TransformCaching').FileBasedCache)('/cache');
transformCache = new (require('../TransformCaching')).FileBasedCache(
'/cache',
);
});
it('is caching different files and options separately', () => {
@ -60,8 +63,10 @@ describe('TransformCaching.FileBasedCache', () => {
getTransformCacheKey: () => 'abcdef',
filePath,
transformOptions,
transformOptionsKey: crypto.createHash('md5')
.update(jsonStableStringify(transformOptions)).digest('hex'),
transformOptionsKey: crypto
.createHash('md5')
.update(jsonStableStringify(transformOptions))
.digest('hex'),
result: {
code: `/* result for ${key} */`,
dependencies: ['foo', `dep of ${key}`],
@ -74,9 +79,7 @@ describe('TransformCaching.FileBasedCache', () => {
['/some/project/sub/dir/file.js', '/some/project/other.js'],
[{foo: 1}, {foo: 2}],
);
allCases.forEach(
entry => transformCache.writeSync(argsFor(entry)),
);
allCases.forEach(entry => transformCache.writeSync(argsFor(entry)));
allCases.forEach(entry => {
const args = argsFor(entry);
const {result} = args;
@ -129,5 +132,4 @@ describe('TransformCaching.FileBasedCache', () => {
expect(cachedResult.outdatedDependencies).toEqual(['foo', 'bar']);
});
});
});

View File

@ -5,7 +5,10 @@
* 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.
*
* @format
*/
'use strict';
var _ = require('lodash');
@ -82,12 +85,20 @@ function formatBanner(message, options) {
var horizontalBorderLine = repeatString(
HORIZONTAL_LINE,
width - marginLeft - marginRight - 2
width - marginLeft - marginRight - 2,
);
var top = spaces(marginLeft) + TOP_LEFT + horizontalBorderLine + TOP_RIGHT +
var top =
spaces(marginLeft) +
TOP_LEFT +
horizontalBorderLine +
TOP_RIGHT +
spaces(marginRight);
var bottom =
spaces(marginLeft) +
BOTTOM_LEFT +
horizontalBorderLine +
BOTTOM_RIGHT +
spaces(marginRight);
var bottom = spaces(marginLeft) + BOTTOM_LEFT + horizontalBorderLine +
BOTTOM_RIGHT + spaces(marginRight);
return _.flattenDeep([top, bodyLines, bottom]).join('\n');
}

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
@ -17,7 +18,10 @@ const {isMappingsMap} = require('./SourceMap');
import type {SourceMap} from './SourceMap';
function relativizeSourceMapInternal(sourceMap: SourceMap, sourcesRoot: string) {
function relativizeSourceMapInternal(
sourceMap: SourceMap,
sourcesRoot: string,
) {
if (!isMappingsMap(sourceMap)) {
for (let i = 0; i < sourceMap.sections.length; i++) {
relativizeSourceMapInternal(sourceMap.sections[i].map, sourcesRoot);
@ -29,7 +33,10 @@ function relativizeSourceMapInternal(sourceMap: SourceMap, sourcesRoot: string)
}
}
function relativizeSourceMap(sourceMap: SourceMap, sourcesRoot?: string): SourceMap {
function relativizeSourceMap(
sourceMap: SourceMap,
sourcesRoot?: string,
): SourceMap {
if (!sourcesRoot) {
return sourceMap;
}

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
@ -23,53 +24,68 @@ export type GlobalCacheDisabledReason = 'too_many_errors' | 'too_many_misses';
* A tagged union of all the actions that may happen and we may want to
* report to the tool user.
*/
export type ReportableEvent = {
port: number,
projectRoots: $ReadOnlyArray<string>,
type: 'initialize_packager_started',
} | {
type: 'initialize_packager_done',
} | {
type: 'initialize_packager_failed',
port: number,
error: Error,
} | {
buildID: string,
type: 'bundle_build_done',
} | {
buildID: string,
type: 'bundle_build_failed',
} | {
buildID: string,
bundleOptions: BundleOptions,
type: 'bundle_build_started',
} | {
error: Error,
type: 'bundling_error',
} | {
type: 'dep_graph_loading',
} | {
type: 'dep_graph_loaded',
} | {
buildID: string,
type: 'bundle_transform_progressed',
transformedFileCount: number,
totalFileCount: number,
} | {
type: 'global_cache_error',
error: Error,
} | {
type: 'global_cache_disabled',
reason: GlobalCacheDisabledReason,
} | {
type: 'transform_cache_reset',
} | {
type: 'worker_stdout_chunk',
chunk: string,
} | {
type: 'worker_stderr_chunk',
chunk: string,
};
export type ReportableEvent =
| {
port: number,
projectRoots: $ReadOnlyArray<string>,
type: 'initialize_packager_started',
}
| {
type: 'initialize_packager_done',
}
| {
type: 'initialize_packager_failed',
port: number,
error: Error,
}
| {
buildID: string,
type: 'bundle_build_done',
}
| {
buildID: string,
type: 'bundle_build_failed',
}
| {
buildID: string,
bundleOptions: BundleOptions,
type: 'bundle_build_started',
}
| {
error: Error,
type: 'bundling_error',
}
| {
type: 'dep_graph_loading',
}
| {
type: 'dep_graph_loaded',
}
| {
buildID: string,
type: 'bundle_transform_progressed',
transformedFileCount: number,
totalFileCount: number,
}
| {
type: 'global_cache_error',
error: Error,
}
| {
type: 'global_cache_disabled',
reason: GlobalCacheDisabledReason,
}
| {
type: 'transform_cache_reset',
}
| {
type: 'worker_stdout_chunk',
chunk: string,
}
| {
type: 'worker_stderr_chunk',
chunk: string,
};
/**
* Code across the application takes a reporter as an option and calls the
@ -99,7 +115,11 @@ export type Reporter = {
* calling this, add a new type of ReportableEvent instead, and implement a
* proper handler in the reporter(s).
*/
function logWarning(terminal: Terminal, format: string, ...args: Array<mixed>): void {
function logWarning(
terminal: Terminal,
format: string,
...args: Array<mixed>
): void {
const str = util.format(format, ...args);
terminal.log('%s: %s', chalk.yellow('warning'), str);
}
@ -107,7 +127,11 @@ function logWarning(terminal: Terminal, format: string, ...args: Array<mixed>):
/**
* Similar to `logWarning`, but for messages that require the user to act.
*/
function logError(terminal: Terminal, format: string, ...args: Array<mixed>): void {
function logError(
terminal: Terminal,
format: string,
...args: Array<mixed>
): void {
const str = util.format(format, ...args);
terminal.log('%s: %s', chalk.red('error'), str);
}

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';