Skip to content

Commit bea889c

Browse files
authored
Avoid loading files that we know are binary ahead of time (#5612)
1 parent 9c0912c commit bea889c

3 files changed

Lines changed: 103 additions & 7 deletions

File tree

packages/jest-haste-map/src/__tests__/index.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,12 @@ describe('HasteMap', () => {
141141
'/vegetables/melon.js': ['/**', ' * @providesModule Melon', ' */'].join(
142142
'\n',
143143
),
144+
'/video/video.mp4': Buffer.from([0xfa, 0xce, 0xb0, 0x0c]).toString(),
144145
});
145146
mockClocks = object({
146147
'/fruits': 'c:fake-clock:1',
147148
'/vegetables': 'c:fake-clock:2',
149+
'/video': 'c:fake-clock:3',
148150
});
149151

150152
mockChangedFiles = null;
@@ -305,6 +307,28 @@ describe('HasteMap', () => {
305307
});
306308
});
307309

310+
it('does not crawl native files even if requested to do so', async () => {
311+
mockFs['/video/i-require-a-video.js'] = [
312+
'/**',
313+
' * @providesModule IRequireAVideo',
314+
' */',
315+
'module.exports = require("./video.mp4");',
316+
].join('\n');
317+
318+
const hasteMap = new HasteMap(
319+
Object.assign({}, defaultConfig, {
320+
extensions: [...defaultConfig.extensions],
321+
roots: [...defaultConfig.roots, '/video'],
322+
}),
323+
);
324+
325+
const {__hasteMapForTest: data} = await hasteMap.build();
326+
327+
expect(data.map.IRequireAVideo).toBeDefined();
328+
expect(data.files['/video/video.mp4']).toBeDefined();
329+
expect(fs.readFileSync).not.toBeCalledWith('/video/video.mp4', 'utf8');
330+
});
331+
308332
it('retains all files if `retainAllFiles` is specified', () => {
309333
mockFs['/fruits/node_modules/fbjs/index.js'] = [
310334
'/**',
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
// This list is compiled after the MDN list of the most common MIME types (see
11+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/
12+
// Complete_list_of_MIME_types).
13+
//
14+
// Only MIME types starting with "image/", "video/", "audio/" and "font/" are
15+
// reflected in the list. Adding "application/" is too risky since some text
16+
// file formats (like ".js" and ".json") have an "application/" MIME type.
17+
//
18+
// Feel free to add any extensions that cannot contain any "@providesModule"
19+
// annotation.
20+
21+
const extensions: Set<string> = new Set([
22+
// JSONs are never haste modules, except for "package.json", which is handled.
23+
'.json',
24+
25+
// Image extensions.
26+
'.bmp',
27+
'.gif',
28+
'.ico',
29+
'.jpeg',
30+
'.jpg',
31+
'.png',
32+
'.svg',
33+
'.tiff',
34+
'.tif',
35+
'.webp',
36+
37+
// Video extensions.
38+
'.avi',
39+
'.mp4',
40+
'.mpeg',
41+
'.mpg',
42+
'.ogv',
43+
'.webm',
44+
'.3gp',
45+
'.3g2',
46+
47+
// Audio extensions.
48+
'.aac',
49+
'.midi',
50+
'.mid',
51+
'.mp3',
52+
'.oga',
53+
'.wav',
54+
'.3gp',
55+
'.3g2',
56+
57+
// Font extensions.
58+
'.eot',
59+
'.otf',
60+
'.ttf',
61+
'.woff',
62+
'.woff2',
63+
]);
64+
65+
export default extensions;

packages/jest-haste-map/src/worker.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import type {HasteImpl, WorkerMessage, WorkerMetadata} from './types';
1212
import path from 'path';
1313
import * as docblock from 'jest-docblock';
1414
import fs from 'graceful-fs';
15+
import blacklist from './blacklist';
1516
import H from './constants';
1617
import extractRequires from './lib/extract_requires';
1718

18-
const JSON_EXTENSION = '.json';
19-
const PACKAGE_JSON = path.sep + 'package' + JSON_EXTENSION;
19+
const PACKAGE_JSON = path.sep + 'package.json';
2020

2121
let hasteImpl: ?HasteImpl = null;
2222
let hasteImplModulePath: ?string = null;
@@ -35,26 +35,33 @@ export async function worker(data: WorkerMessage): Promise<WorkerMetadata> {
3535
}
3636

3737
const filePath = data.filePath;
38-
const content = fs.readFileSync(filePath, 'utf8');
3938
let module;
4039
let id: ?string;
4140
let dependencies;
4241

4342
if (filePath.endsWith(PACKAGE_JSON)) {
44-
const fileData = JSON.parse(content);
43+
const fileData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
44+
4545
if (fileData.name) {
4646
id = fileData.name;
4747
module = [filePath, H.PACKAGE];
4848
}
49-
} else if (!filePath.endsWith(JSON_EXTENSION)) {
49+
50+
return {dependencies, id, module};
51+
}
52+
53+
if (!blacklist.has(filePath.substr(filePath.lastIndexOf('.')))) {
54+
const content = fs.readFileSync(filePath, 'utf8');
55+
5056
if (hasteImpl) {
5157
id = hasteImpl.getHasteName(filePath);
5258
} else {
5359
const doc = docblock.parse(docblock.extract(content));
54-
const idPragmas = [].concat(doc.providesModule || doc.provides);
55-
id = idPragmas[0];
60+
id = [].concat(doc.providesModule || doc.provides)[0];
5661
}
62+
5763
dependencies = extractRequires(content);
64+
5865
if (id) {
5966
module = [filePath, H.MODULE];
6067
}

0 commit comments

Comments
 (0)