Skip to content

Commit 51ffc5c

Browse files
huntiefacebook-github-bot
authored andcommitted
Break out URLSearchParams, require typedef for unparsable files (#45783)
Summary: Pull Request resolved: #45783 Improves type strictness in the `react-native` package. - Break out `URLSearchParams` from `URL.js` into its own module, to isolate a `$FlowFixMe[unsupported-syntax]` suppression within that definition. - Update `public-api-test` to require an adjacent `<module>.js.flow` type definition file whenever a `$FlowFixMe[unsupported-syntax]`is present. - Add `URLSearchParams.js.flow` with a Flow parser compatible typedef (`@iterator` instead of `[Symbol.iterator]`). The result of these changes is to add missing typedef test coverage for `Libraries/Blob/URL.js` (see updated test snapshots). Changelog: [Internal] Reviewed By: hoxyq Differential Revision: D60376327 fbshipit-source-id: 93c0949289a4b53f621f563769ffb68d5dc38d91
1 parent 0e9c9c7 commit 51ffc5c

5 files changed

Lines changed: 154 additions & 67 deletions

File tree

packages/react-native/Libraries/Blob/URL.js

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (
2727
}
2828
}
2929

30-
/**
30+
/*
3131
* To allow Blobs be accessed via `content://` URIs,
3232
* you need to register `BlobProvider` as a ContentProvider in your app's `AndroidManifest.xml`:
3333
*
@@ -52,67 +52,7 @@ if (
5252
* ```
5353
*/
5454

55-
// Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/src
56-
// The reference code bloat comes from Unicode issues with URLs, so those won't work here.
57-
export class URLSearchParams {
58-
_searchParams: Array<Array<string>> = [];
59-
60-
constructor(params: any) {
61-
if (typeof params === 'object') {
62-
Object.keys(params).forEach(key => this.append(key, params[key]));
63-
}
64-
}
65-
66-
append(key: string, value: string): void {
67-
this._searchParams.push([key, value]);
68-
}
69-
70-
delete(name: string): void {
71-
throw new Error('URLSearchParams.delete is not implemented');
72-
}
73-
74-
get(name: string): void {
75-
throw new Error('URLSearchParams.get is not implemented');
76-
}
77-
78-
getAll(name: string): void {
79-
throw new Error('URLSearchParams.getAll is not implemented');
80-
}
81-
82-
has(name: string): void {
83-
throw new Error('URLSearchParams.has is not implemented');
84-
}
85-
86-
set(name: string, value: string): void {
87-
throw new Error('URLSearchParams.set is not implemented');
88-
}
89-
90-
sort(): void {
91-
throw new Error('URLSearchParams.sort is not implemented');
92-
}
93-
94-
// $FlowFixMe[unsupported-syntax]
95-
// $FlowFixMe[missing-local-annot]
96-
[Symbol.iterator]() {
97-
return this._searchParams[Symbol.iterator]();
98-
}
99-
100-
toString(): string {
101-
if (this._searchParams.length === 0) {
102-
return '';
103-
}
104-
const last = this._searchParams.length - 1;
105-
return this._searchParams.reduce((acc, curr, index) => {
106-
return (
107-
acc +
108-
encodeURIComponent(curr[0]) +
109-
'=' +
110-
encodeURIComponent(curr[1]) +
111-
(index === last ? '' : '&')
112-
);
113-
}, '');
114-
}
115-
}
55+
export {URLSearchParams} from './URLSearchParams';
11656

11757
function validateBaseUrl(url: string) {
11858
// from this MIT-licensed gist: https://gist.github.com/dperini/729294
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
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+
* @format
8+
* @flow
9+
*/
10+
11+
// Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/src
12+
// The reference code bloat comes from Unicode issues with URLs, so those won't work here.
13+
export class URLSearchParams {
14+
_searchParams: Array<Array<string>> = [];
15+
16+
constructor(params: any) {
17+
if (typeof params === 'object') {
18+
Object.keys(params).forEach(key => this.append(key, params[key]));
19+
}
20+
}
21+
22+
append(key: string, value: string): void {
23+
this._searchParams.push([key, value]);
24+
}
25+
26+
delete(name: string): void {
27+
throw new Error('URLSearchParams.delete is not implemented');
28+
}
29+
30+
get(name: string): void {
31+
throw new Error('URLSearchParams.get is not implemented');
32+
}
33+
34+
getAll(name: string): void {
35+
throw new Error('URLSearchParams.getAll is not implemented');
36+
}
37+
38+
has(name: string): void {
39+
throw new Error('URLSearchParams.has is not implemented');
40+
}
41+
42+
set(name: string, value: string): void {
43+
throw new Error('URLSearchParams.set is not implemented');
44+
}
45+
46+
sort(): void {
47+
throw new Error('URLSearchParams.sort is not implemented');
48+
}
49+
50+
// $FlowFixMe[unsupported-syntax]
51+
// $FlowFixMe[missing-local-annot]
52+
[Symbol.iterator]() {
53+
return this._searchParams[Symbol.iterator]();
54+
}
55+
56+
toString(): string {
57+
if (this._searchParams.length === 0) {
58+
return '';
59+
}
60+
const last = this._searchParams.length - 1;
61+
return this._searchParams.reduce((acc, curr, index) => {
62+
return (
63+
acc +
64+
encodeURIComponent(curr[0]) +
65+
'=' +
66+
encodeURIComponent(curr[1]) +
67+
(index === last ? '' : '&')
68+
);
69+
}, '');
70+
}
71+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
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+
* @format
8+
* @flow
9+
*/
10+
11+
declare export class URLSearchParams {
12+
_searchParams: Array<Array<string>>;
13+
constructor(params: any): void;
14+
append(key: string, value: string): void;
15+
delete(name: string): void;
16+
get(name: string): void;
17+
getAll(name: string): void;
18+
has(name: string): void;
19+
set(name: string, value: string): void;
20+
sort(): void;
21+
@@iterator: Iterator<Array<string>>;
22+
toString(): string;
23+
}

packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,48 @@ declare export default typeof NativeFileReaderModule;
15071507
"
15081508
`;
15091509

1510-
exports[`public API should not change unintentionally Libraries/Blob/URL.js 1`] = `"UNTYPED MODULE (unsupported-syntax suppression)"`;
1510+
exports[`public API should not change unintentionally Libraries/Blob/URL.js 1`] = `
1511+
"export { URLSearchParams } from \\"./URLSearchParams\\";
1512+
declare export class URL {
1513+
_url: string;
1514+
_searchParamsInstance: ?URLSearchParams;
1515+
static createObjectURL(blob: Blob): string;
1516+
static revokeObjectURL(url: string): void;
1517+
constructor(url: string, base: string | URL): void;
1518+
get hash(): string;
1519+
get host(): string;
1520+
get hostname(): string;
1521+
get href(): string;
1522+
get origin(): string;
1523+
get password(): string;
1524+
get pathname(): string;
1525+
get port(): string;
1526+
get protocol(): string;
1527+
get search(): string;
1528+
get searchParams(): URLSearchParams;
1529+
toJSON(): string;
1530+
toString(): string;
1531+
get username(): string;
1532+
}
1533+
"
1534+
`;
1535+
1536+
exports[`public API should not change unintentionally Libraries/Blob/URLSearchParams.js.flow 1`] = `
1537+
"declare export class URLSearchParams {
1538+
_searchParams: Array<Array<string>>;
1539+
constructor(params: any): void;
1540+
append(key: string, value: string): void;
1541+
delete(name: string): void;
1542+
get(name: string): void;
1543+
getAll(name: string): void;
1544+
has(name: string): void;
1545+
set(name: string, value: string): void;
1546+
sort(): void;
1547+
@@iterator: Iterator<Array<string>>;
1548+
toString(): string;
1549+
}
1550+
"
1551+
`;
15111552

15121553
exports[`public API should not change unintentionally Libraries/BugReporting/BugReporting.js 1`] = `
15131554
"type ExtraData = { [key: string]: string, ... };

packages/react-native/Libraries/__tests__/public-api-test.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import type {TransformVisitor} from 'hermes-transform';
1313

1414
const translate = require('flow-api-translator');
15-
const {promises: fs} = require('fs');
15+
const {existsSync, promises: fs} = require('fs');
1616
const glob = require('glob');
1717
const {transform} = require('hermes-transform');
1818
const path = require('path');
@@ -47,10 +47,22 @@ describe('public API', () => {
4747
const source = await fs.readFile(path.join(PACKAGE_ROOT, file), 'utf-8');
4848

4949
if (/@flow/.test(source)) {
50+
// Require and use adjacent .js.flow file when source file includes an
51+
// unsupported-syntax suppression
5052
if (source.includes('// $FlowFixMe[unsupported-syntax]')) {
51-
expect(
52-
'UNTYPED MODULE (unsupported-syntax suppression)',
53-
).toMatchSnapshot();
53+
const flowDefPath = path.join(
54+
PACKAGE_ROOT,
55+
file.replace('.js', '.js.flow'),
56+
);
57+
58+
if (!existsSync(flowDefPath)) {
59+
throw new Error(
60+
'Found an unsupported-syntax suppression in ' +
61+
file +
62+
', meaning types cannot be parsed. Add an adjacent <module>.js.flow file to fix this!',
63+
);
64+
}
65+
5466
return;
5567
}
5668

0 commit comments

Comments
 (0)