react-native/jest/preprocessor.js

126 lines
4.3 KiB
JavaScript
Raw Normal View History

2015-09-16 17:30:53 +00:00
/**
* Copyright (c) Facebook, Inc. and its affiliates.
2015-09-16 17:30:53 +00:00
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
2015-09-16 17:30:53 +00:00
*/
/* eslint-env node */
2015-09-16 17:30:53 +00:00
'use strict';
const {transformSync: babelTransformSync} = require('@babel/core');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const babelRegisterOnly = require('metro-babel-register');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
const generate = require('@babel/generator').default;
2015-09-16 17:30:53 +00:00
const nodeFiles = new RegExp(
[
'/metro(?:-[^/]*)?/', // metro, metro-core, metro-source-map, metro-etc.
].join('|'),
);
const nodeOptions = babelRegisterOnly.config([nodeFiles]);
create better debuggable source maps Summary: Introduces a new mechanism to build source maps that allows us to use real mapping segments instead of just mapping line-by-line. This mechanism is only used when building development bundles to improve the debugging experience in Chrome. The new mechanism takes advantage of a new feature in babel-generator that exposes raw mapping objects. These raw mapping objects are converted to arrays with 2, 4, or 5 for the most compact representation possible. We no longer generate a source map for the bundle that maps each line to itself in conjunction with configuring babel generator to retain lines. Instead, we create a source map with a large mappings object produced from the mappings of each individual file in conjunction with a “carry over” – the number of preceding lines in the bundle. The implementation makes a couple of assumptions that hold true for babel transform results, e.g. mappings being in the order of the generated code, and that a block of mappings always belongs to the same source file. In addition, the implementation avoids allocation of objects and strings at all costs. All calculations are purely numeric, and base64 vlq produces numeric ascii character codes. These are written to a preallocated buffer objects, which is turned to a string only at the end of the building process. This implementation is ~5x faster than using the source-map library. In addition to providing development source maps that work better, we can now also produce individual high-quality source maps for production builds and combine them to an “index source map”. This approach is unfeasable for development source maps, because index source map consistently crash Chrome. Better production source maps are useful to get precise information about source location and symbol names when symbolicating stack traces from crashes in production. Reviewed By: jeanlauliac Differential Revision: D4382290 fbshipit-source-id: 365a176fa142729d0a4cef43edeb81084361e54d
2017-01-12 22:21:59 +00:00
babelRegisterOnly([]);
const transformer = require('metro-react-native-babel-transformer');
2015-09-16 17:30:53 +00:00
module.exports = {
process(src /*: string */, file /*: string */) {
if (nodeFiles.test(file)) {
// node specific transforms only
return babelTransformSync(src, {
filename: file,
sourceType: 'script',
...nodeOptions,
ast: false,
}).code;
}
const {ast} = transformer.transform({
filename: file,
options: {
ast: true, // needed for open source (?) https://github.com/facebook/react-native/commit/f8d6b97140cffe8d18b2558f94570c8d1b410d5c#r28647044
dev: true,
enableBabelRuntime: false,
experimentalImportSupport: false,
hot: false,
inlineRequires: true,
Standarize options passed to the transformer Summary: This is the first step to make transformers fully customizable (and not be tied to JS, or RN). In order to do that, I'm changing the signature of the transformers, which currently is: ``` function transformCode( filename: string, localPath: LocalPath, transformerPath: string, options: WorkerOptions, assetExts: $ReadOnlyArray<string>, assetRegistryPath: string, minifierPath: string, asyncRequireModulePath: string, dynamicDepsInPackages: DynamicRequiresBehavior, ) ``` to be: ``` async function transformCode( filename: string, localPath: LocalPath, options: WorkerOptions, ) ``` (so basically, all the RN-custom properties are moved to `WorkerOptions`, which in the future will be a generic to allow anybody pass any random option to their transformers). In order to make all this work, I've had to get rid of the logic that calculates the base cache key hash based on a subset of worker options (the ones that Metro knows that are not going to change between runs). This could potentially cause a perf regression (since we're now making the hash calculation a bit more costly), and in fact I could measure a ~400ms regression on the worse case scenario (which happens when restarting Metro and re-transforming a Wilde from a warm local cache). I've benchmarked this regression and could find that it's caused by the array of `assetExtensions` (which is potentially large). I have a followup diff to improve this, which is able to remove the regression completely. Reviewed By: pvdz Differential Revision: D8695766 fbshipit-source-id: eccd18a4cbc91854f34d5c9ba7f95088f19483a1
2018-08-23 22:44:38 +00:00
minify: false,
platform: '',
projectRoot: '',
Adds support for `publicPath` to enable serving assets from different locations. (#299) Summary: <!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. The two fields below are mandatory. --> **Summary** <!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? --> This is an updated followup from https://github.com/facebook/metro/pull/280, which we would still need to address the following assumptions about `/assets/`: https://github.com/facebook/metro/blob/e7deea19001d903a47868bb1fe6456bdc4b585e7/packages/metro/src/Server.js#L332 https://github.com/facebook/metro/blob/e7deea19001d903a47868bb1fe6456bdc4b585e7/packages/metro/src/Server.js#L379 https://github.com/facebook/metro/blob/e7deea19001d903a47868bb1fe6456bdc4b585e7/packages/metro/src/Server.js#L385 As pointed out by gdborton, there isn't currently a way to make this a configurable option. I am not certain how to find a proper workaround for `processRequest`. We found a temporary solution to have our express app pick up serving the assets from a publicPath as a middleware. But the change in this PR is still necessary to get it working fully. **Test plan** <!-- Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes UI. --> - Will add tests once we figure out a comprehensive solution Pull Request resolved: https://github.com/facebook/metro/pull/299 Reviewed By: rafeca Differential Revision: D12939229 Pulled By: mjesun fbshipit-source-id: 769c23468c5ac434f8319e5e7caaf46dd6453f2d
2018-11-09 13:49:04 +00:00
publicPath: '/assets',
retainLines: true,
sourceType: 'unambiguous', // b7 required. detects module vs script mode
},
src,
plugins: [
[require('@babel/plugin-transform-block-scoping')],
// the flow strip types plugin must go BEFORE class properties!
// there'll be a test case that fails if you don't.
[require('@babel/plugin-transform-flow-strip-types')],
[
require('@babel/plugin-proposal-class-properties'),
// use `this.foo = bar` instead of `this.defineProperty('foo', ...)`
{loose: true},
],
[require('@babel/plugin-transform-computed-properties')],
[require('@babel/plugin-transform-destructuring')],
[require('@babel/plugin-transform-function-name')],
[require('@babel/plugin-transform-literals')],
[require('@babel/plugin-transform-parameters')],
[require('@babel/plugin-transform-shorthand-properties')],
[require('@babel/plugin-transform-react-jsx')],
[require('@babel/plugin-transform-regenerator')],
[require('@babel/plugin-transform-sticky-regex')],
[require('@babel/plugin-transform-unicode-regex')],
[
require('@babel/plugin-transform-modules-commonjs'),
{strict: false, allowTopLevelThis: true},
],
[require('@babel/plugin-transform-classes')],
[require('@babel/plugin-transform-arrow-functions')],
[require('@babel/plugin-transform-spread')],
[require('@babel/plugin-proposal-object-rest-spread')],
[
require('@babel/plugin-transform-template-literals'),
{loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
],
[require('@babel/plugin-transform-exponentiation-operator')],
[require('@babel/plugin-transform-object-assign')],
[require('@babel/plugin-transform-for-of'), {loose: true}],
[require('@babel/plugin-transform-react-display-name')],
[require('@babel/plugin-transform-react-jsx-source')],
],
});
return generate(
ast,
{
code: true,
comments: false,
compact: false,
filename: file,
retainLines: true,
sourceFileName: file,
sourceMaps: true,
},
src,
).code;
},
getCacheKey: createCacheKeyFunction([
__filename,
require.resolve('metro-react-native-babel-transformer'),
require.resolve('@babel/core/package.json'),
]),
2015-09-16 17:30:53 +00:00
};