Skip to content

Commit

Permalink
Merge branch 'main' into @evanbacon/require-context/resolve-file-paths
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanBacon committed Jun 22, 2022
2 parents 5852acb + 100ca6f commit 12fcb4c
Show file tree
Hide file tree
Showing 97 changed files with 4,766 additions and 1,604 deletions.
11 changes: 10 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ module.exports = {
env: {
node: true,
},
root: true,
extends: ['eslint-config-fb-strict', 'plugin:prettier/recommended'],
plugins: ['babel', 'flowtype', 'import', 'lint', 'prettier'],
parser: 'babel-eslint',
parser: 'hermes-eslint',
rules: {
'babel/quotes': ['error', 'single', 'avoid-escape'],
'consistent-return': 'error',
Expand All @@ -35,6 +36,14 @@ module.exports = {
quotes: 'off',
'sort-keys': 'off',
'flowtype/object-type-delimiter': 'off',

// These rules are not required with hermes-eslint
'ft-flow/define-flow-type': 0,
'ft-flow/use-flow-type': 0,
'flowtype/define-flow-type': 0,
'flowtype/use-flow-type': 0,
// flow handles this check for us, so it's not required
'no-undef': 0,
},
overrides: [
{
Expand Down
2 changes: 1 addition & 1 deletion .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ untyped-import
untyped-type-import

[version]
^0.178.1
^0.180.0
3 changes: 3 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ jobs:
- yarn_install
- yarn_run:
command: test-ci
- yarn_run:
command: test-smoke


test-node-12:
docker:
Expand Down
35 changes: 35 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ module.exports = {
},
server: {
/* server options */
},
watcher: {
/* watcher options */
watchman: {
/* Watchman-specific options */
}
}
};
```
Expand Down Expand Up @@ -211,6 +217,16 @@ Type: `Array<string>`

Additional platforms to look out for, For example, if you want to add a "custom" platform, and use modules ending in .custom.js, you would return ['custom'] here.

#### `requireCycleIgnorePatterns`

Type: `Array<RegExp>`

In development mode, suppress require cycle warnings for any cycle involving a module that matches any of these expressions. This is useful for third-party code and first-party expected cycles.

Note that if you specify your own value for this config option it will replace (not concatenate with) Metro's default.

Defaults to `[/(^|\/|\\)node_modules($|\/|\\)/]`.

---
### Transformer Options

Expand Down Expand Up @@ -373,6 +389,25 @@ Type: `boolean` (default: `true`)

Run Inspector Proxy server inside Metro to be able to inspect React Native code.

---

### Watcher Options

Options for the filesystem watcher.

:::note

Dot notation in this section indicates a nested configuration object, e.g. `watchman.deferStates``watchman: { deferStates: ... }`.

:::

#### `watchman.deferStates`

Type: `Array<string>`

Applies when using Watchman. Metro will [defer processing filesystem updates](https://facebook.github.io/watchman/docs/cmd/subscribe.html#defer) while these [states](https://facebook.github.io/watchman/docs/cmd/state-enter.html) are asserted in the watch. This is useful for debouncing builds while the filesystem hasn't settled, e.g. during large source control operations.

The default value is `['hg.update']`.

## Merging Configurations

Expand Down
137 changes: 137 additions & 0 deletions docs/SourceMapFormat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
id: source-map-format
title: Source Map Format
---

Metro produces standard [source maps](https://sourcemaps.info/spec.html) along with its JavaScript bundle output. In addition to the standard information, Metro encodes extra information in [vendor-specific fields](https://sourcemaps.info/spec.html#h.ghqpj1ytqjbm) within the source map. This page serves as a specification for this encoding.

:::note
The content on this page assumes familiarity with the [source map specification](https://sourcemaps.info/spec.html). Check out [Anatomy of source maps](https://www.bugsnag.com/blog/source-maps) for a general introduction to source maps and how they work.
:::

## `x_facebook_sources`

The `x_facebook_sources` field encodes metadata about source files in a source map. Each piece of metadata represents some attribute intrinsic to the source code of that particular file - for example, the result of running some analysis over the AST. This allows tools such as debuggers and JS engines to access such analyses efficiently, without needing to parse or even have access to the source code.

In the same way that the standard [`sources`](https://sourcemaps.info/spec.html#h.ghqpj1ytqjbm:~:text=sourceRoot%22%3A%20%22%22%2C-,%22sources%22%3A,-%5B%22foo.js%22%2C%20%22bar) field is a list of source URLs and [`sourcesContent`](https://sourcemaps.info/spec.html#h.ghqpj1ytqjbm:~:text=js%22%2C%20%22bar.js%22%5D%2C-,%22sourcesContent%22%3A,-%5Bnull%2C%20null%5D%2C) is a list of (optional) source code strings, `x_facebook_sources` is a list of optional **metadata tuples**. The _i_-th metadata tuple (`x_facebook_sources[i]`) corresponds to the source file whose URL is `sources[i]`.

In nested (indexed) source maps, `x_facebook_sources` may appear as part of any nested source map in [`sections`](https://sourcemaps.info/spec.html#h.535es3xeprgt) that itself has a `sources` field.

If present, `x_facebook_sources` may be a different length than `sources` (but usually shouldn't be). In particular, if it's shorter than `sources`, `x_facebook_sources` interpreted as if it were padded with `null` values to match the length of `sources`.

:::info
If you are writing a tool that processes source maps generated by Metro, and want to generate a new source map containing a valid `x_facebook_sources` field, you'll mainly need to ensure that `x_facebook_sources[i]` still corresponds to `sources[i]` in the output - even if your tool reorders, adds or deletes elements in `sources`. Notably, this can be done *without* parsing/decoding the metadata tuples: unless your tool actively needs to access the information within them, you can treat them as opaque blobs of JSON.

If a tool cannot guarantee that the `sources` and `x_facebook_sources` arrays will stay in sync, it should delete the `x_facebook_sources` field from its output.
:::

### Metadata tuple

Each metadata tuple is encoded as an array of zero or more entries. Each entry may be `null` to signify that it's missing. A run of trailing `null`s may be truncated from the end of the tuple with no change in meaning. The metadata tuple itself may also be `null` to signify that the source file has no associated metadata.

The indices in each metadata tuple are assigned as follows:

* Index 0: [Function map](#function-map) or `null`.
* In Metro, this is the result of calling [`generateFunctionMap`](https://github.com/facebook/metro/blob/main/packages/metro-source-map/src/generateFunctionMap.js) on the source AST.
* Index 1-∞: Reserved for future use.

#### Function map

A function map is encoded as an object with the following two fields:

* `names`: An array of strings.
* `mappings`: A string following the [encoding](#function-map-mappings-field-encoding) described below.

When decoded, `mappings` represents a list of 3-tuples of integers: `(column, nameIndex, line), (column, nameIndex, line), ...`. The list is ordered by `line` and then `column`.

The presence of a 3-tuple `(column, nameIndex, line)` means that the _local function name_ in the code region beginning at `line` and `column` (in the source file described by the current metadata tuple) is `names[nameIndex]`.

##### Function map `mappings` field encoding

The value of the `mappings` field is described by the _Mappings_ production of the grammar detailed below.

1. `Mappings = [ ";" ] LineMappings { ";" { ";" } LineMappings }`
2. `LineMappings = FirstColumnMapping "," ColumnMapping`
3. `FirstColumnMapping = VLQ VLQ VLQ`
4. `ColumnMapping = VLQ VLQ [ VLQ ]`
5. `VLQ =` _A single Base64-encoded variable-length quantity, as defined in the [source map specification](https://sourcemaps.info/spec.html#h.crcf4lqeivt8)_.

:::note
The above grammar uses the following BNF-like notation:

| Notation | Meaning |
|-|-|
| `[ X ]` | _X_ appears zero or 1 times. |
| `{ X }` | _X_ appears 0 or more times. |
| `"foo"` | The literal characters `foo`. |

:::

The three VLQs in _FirstColumnMapping_ or _ColumnMapping_ represent, in this order:
1. **Column delta**:
* In _FirstColumnMapping_: The column offset from the beginning of the line. (0 = first column)
* In _ColumnMapping_: The column offset from the last-encountered _FirstColumnMapping_ or _ColumnMapping_.
2. **Name delta**: The name index offset from the last-encountered _FirstColumnMapping_ or _ColumnMapping_. This is *not* reset between lines.
3. **Line delta**: The line offset from the last-encountered _FirstColumnMapping_ or _ColumnMapping_. This is *not* reset between lines.
* This MUST be 0 (Base64 VLQ: `A`) if it is part of a _ColumnMapping_.
* Implementations SHOULD omit this field from the encoded form of _ColumnMapping_.

### Example

Given a single source file called `file.js`, a complete source map might look like this:

:::note
Comments are for illustrative purposes - the source map format does not allow comments.
:::

```json
{
"version": 3,
"sources": ["file.js"],
"sourcesContent": ["function a(){} function b(){}"],
"mappings": "AAAA", // NOTE: Simplified
"x_facebook_sources": [
// Metadata tuple for source #0 (file.js)
[
// Metadata item #0.0 = function map for source #0 (file.js)
{
// a from 1:0
// <global> from 1:14
// b from 1:15
// (See detailed decoding procedure below.)
"mappings": "AAA,cC,CC",
"names": [
"a",
"<global>",
"b",
]
}
]
]
}
```

The decoding procedure for the function map in the above example is illustrated by the following code:

```js
const decoded = [];
const names = ['a', '<global>', 'b']; // From the function map

let column = 0, nameIndex = 0, line = 1;
column += 0 /* A */; nameIndex += 0 /* A */; line += 0 /* A */;
decoded.push({column, name: names[nameIndex] /* 'a' */, line});

column += 14 /* c */; nameIndex += 1 /* C */; // no line delta
decoded.push({column, name: names[nameIndex] /* '<global>' */, line});

column += 1 /* C */; nameIndex += 1 /* C */; // no line delta
decoded.push({column, name: names[nameIndex] /* 'b' */, line});

/*
decoded = [
{column: 0, name: 'a', line: 1},
{column: 14, name: '<global>', line: 1},
{column: 15, name: 'b', line: 1},
]
*/
```
2 changes: 1 addition & 1 deletion eslint-rules/__tests__/strictly-null-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const rule = require('../strictly-null.js');
const ESLintTester = require('eslint').RuleTester;

ESLintTester.setDefaultConfig({
parser: require.resolve('babel-eslint'),
parser: require.resolve('hermes-eslint'),
parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"lerna": "2.4.0",
"version": "0.71.0",
"version": "0.71.1",
"npmClient": "yarn",
"useWorkspaces": true
}
17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"@babel/plugin-syntax-class-properties": "^7.0.0",
"@babel/plugin-transform-flow-strip-types": "^7.0.0",
"@babel/plugin-transform-modules-commonjs": "^7.0.0",
"acorn": "^5.1.2",
"babel-eslint": "^10.1.0",
"acorn": "^8.7.1",
"babel-jest": "^26.6.3",
"chalk": "^4.0.0",
"codecov": "^3.6.5",
Expand All @@ -25,12 +24,15 @@
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-relay": "^1.8.2",
"flow-bin": "^0.178.1",
"flow-bin": "^0.180.0",
"glob": "^7.1.1",
"hermes-eslint": "0.8.0",
"istanbul-api": "3.0.0",
"istanbul-lib-coverage": "3.0.0",
"jest": "^26.6.3",
"jest-watch-typeahead": "^0.6.0",
"lerna": "2.4.0",
"metro-babel-register": "*",
"micromatch": "^4.0.4",
"prettier": "^2.4.1",
"progress": "^2.0.0",
Expand All @@ -42,13 +44,15 @@
"build": "node ./scripts/build.js",
"clean-all": "rm -rf ./node_modules && rm -rf ./packages/*/node_modules && yarn run build-clean",
"jest-coverage": "yarn run jest --coverage",
"lint": "eslint . --cache",
"lint-fix": "eslint . --fix --cache",
"lint": "eslint . --cache",
"postinstall": "node ./scripts/build.js",
"postpublish": "lerna run cleanup-release",
"preinstall": "node ./scripts/preinstall.js",
"publish": "yarn run build-clean && yarn run build && lerna run prepare-release && lerna exec -- npm publish",
"postpublish": "lerna run cleanup-release",
"start": "node packages/metro/src/cli",
"test-ci": "yarn run typecheck && yarn run lint && yarn run build && yarn run jest-coverage -i && node scripts/mapCoverage.js && codecov",
"test-smoke": "yarn start build --config packages/metro/src/integration_tests/metro.config.js TestBundle.js --out /tmp/TestBundle",
"test": "yarn run typecheck && yarn run lint && yarn run build && yarn run jest",
"typecheck": "flow check",
"update-version": "node ./scripts/updateVersion"
Expand All @@ -68,7 +72,8 @@
},
"setupFiles": [
"<rootDir>/scripts/setupJest.js"
]
],
"watchPlugins": ["jest-watch-typeahead/filename", "jest-watch-typeahead/testname"]
},
"license": "MIT",
"dependencies": {}
Expand Down
4 changes: 2 additions & 2 deletions packages/buck-worker-tool/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "buck-worker-tool",
"version": "0.71.0",
"version": "0.71.1",
"description": "Implementation of the Buck worker protocol for Node.js.",
"license": "MIT",
"main": "src/worker-tool.js",
Expand All @@ -13,7 +13,7 @@
"through": ">=2.2.7 <3"
},
"devDependencies": {
"metro-memory-fs": "0.71.0"
"metro-memory-fs": "0.71.1"
},
"scripts": {
"prepare-release": "test -d build && rm -rf src.real && mv src src.real && mv build src",
Expand Down
2 changes: 1 addition & 1 deletion packages/metro-babel-register/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-babel-register",
"version": "0.71.0",
"version": "0.71.1",
"description": "🚇 babel/register configuration for Metro.",
"main": "src/babel-register.js",
"repository": {
Expand Down
33 changes: 33 additions & 0 deletions packages/metro-babel-register/src/babel-register.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
'use strict';

const escapeRegExp = require('escape-string-regexp');
const fs = require('fs');
const path = require('path');

let _only = [];
Expand Down Expand Up @@ -104,6 +105,38 @@ function buildRegExps(basePath, dirPaths) {
);
}

let isRegisteredForMetroMonorepo = false;

function registerForMetroMonorepo() {
// Noop if we have already registered Babel here.
if (isRegisteredForMetroMonorepo) {
return;
}
// Noop if we are in NODE_ENV=production.
if (process.env.NODE_ENV === 'production') {
return;
}
// Noop if we seem to be outside of the Metro source tree.
if (
!__dirname.endsWith(
['', 'packages', 'metro-babel-register', 'src'].join(path.sep),
)
) {
return;
}
// Bail out if prepare-release has run here.
if (
fs.existsSync(
path.join(__dirname, '..', 'src.real', path.basename(__filename)),
)
) {
return;
}
register([path.resolve(__dirname, '..', '..')]);
isRegisteredForMetroMonorepo = true;
}

module.exports = register;
module.exports.config = config;
module.exports.buildRegExps = buildRegExps;
module.exports.unstable_registerForMetroMonorepo = registerForMetroMonorepo;
6 changes: 3 additions & 3 deletions packages/metro-babel-transformer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-babel-transformer",
"version": "0.71.0",
"version": "0.71.1",
"description": "🚇 Base Babel transformer for Metro.",
"main": "src/index.js",
"repository": {
Expand All @@ -18,8 +18,8 @@
"license": "MIT",
"dependencies": {
"@babel/core": "^7.14.0",
"hermes-parser": "0.6.0",
"metro-source-map": "0.71.0",
"hermes-parser": "0.8.0",
"metro-source-map": "0.71.1",
"nullthrows": "^1.1.1"
}
}

0 comments on commit 12fcb4c

Please sign in to comment.