Skip to content

Commit

Permalink
RN: Enforce flow-typed Signatures
Browse files Browse the repository at this point in the history
Summary:
Creates a new `valid-flow-typed-signature` ESLint rule that validates the `flow-typed` signatures at the top of each file.

This lint rule will discourage contributors from locally forking the `flow-typed` definitions. Instead, any changes should be submitted as patches to the upstream definition in: https://github.com/flow-typed/flow-typed

Changelog:
[Internal]

Reviewed By: rickhanlonii

Differential Revision: D39868721

fbshipit-source-id: e5e3ffe7568dbe52c9b598b53110b0fcbcad3e38
  • Loading branch information
yungsters authored and facebook-github-bot committed Sep 30, 2022
1 parent b846849 commit 4363626
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
1 change: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
**/staticBundle.js
docs/generatedComponentApiDocs.js
flow/
flow-typed/
Libraries/Renderer/*
Libraries/vendor/**/*
node_modules/
Expand Down
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ module.exports = {
{
files: ['flow-typed/**/*.js'],
rules: {
'lint/valid-flow-typed-signature': 2,
'no-unused-vars': 0,
quotes: 0,
},
},
Expand Down
48 changes: 48 additions & 0 deletions tools/eslint/rules/__tests__/valid-flow-typed-signature-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/

'use strict';

const rule = require('../valid-flow-typed-signature.js');
const {RuleTester} = require('eslint');

const ruleTester = new RuleTester({
parser: require.resolve('hermes-eslint'),
parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
},
});

ruleTester.run('valid-flow-typed-signature', rule, {
valid: [
{
code: `// ...`,
},
{
code: [
`// flow-typed signature: 9333721862f426d869c32ea6f7cecfda`,
`// flow-typed version: 123456/xyz_v1.x.x/flow_>=v0.83.x`,
``,
`declare module "xyz" {}`,
].join('\n'),
},
],
invalid: [
{
code: [
`// flow-typed signature: 90affbd9a1954ec9ff029b7ad7183a16`,
`// flow-typed version: 123456/xyz_v1.x.x/flow_>=v0.83.x`,
``,
`declare module "xyz" {}`,
].join('\n'),
errors: [{messageId: 'invalidSignature'}],
},
],
});
71 changes: 71 additions & 0 deletions tools/eslint/rules/valid-flow-typed-signature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/

'use strict';

const crypto = require('node:crypto');

// @see https://github.com/flow-typed/flow-typed
const HASH_COMMENT_RE = /\/\/ flow-typed signature: (.*)$/;

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Require valid flow-typed signatures',
recommended: true,
},
messages: {
invalidSignature:
'Invalid flow-typed signature; avoid local modifications',
},
schema: [],
},

create(context) {
return {
Program() {
const sourceText = context.getSourceCode().getText();

const firstLineEndIndex = sourceText.indexOf('\n');
const firstLine = sourceText.substr(0, firstLineEndIndex);

const match = firstLine.match(HASH_COMMENT_RE);
if (match == null) {
// Not a signed flow-typed definition file.
return;
}

const hash = match[1];
const versionedCode = sourceText.substr(firstLineEndIndex + 1);
if (md5(versionedCode) === hash) {
return;
}

context.report({
loc: {
start: {
line: 1,
column: firstLine.length - hash.length,
},
end: {
line: 1,
column: firstLine.length,
},
},
messageId: 'invalidSignature',
});
},
};
},
};

function md5(string) {
return crypto.createHash('md5').update(string).digest('hex');
}

0 comments on commit 4363626

Please sign in to comment.