Skip to content

Commit eeb6f10

Browse files
authored
Merge branch 'main' into main
2 parents 84da532 + 85de6fd commit eeb6f10

File tree

215 files changed

+6749
-4659
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

215 files changed

+6749
-4659
lines changed

.circleci/config.yml

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,33 @@ jobs:
151151
- setup_node_modules
152152
- run:
153153
name: Download artifacts for base revision
154+
# TODO: The download-experimental-build.js script works by fetching
155+
# artifacts from CI. CircleCI recently updated this endpoint to
156+
# require an auth token. This is a problem for PR branches, where
157+
# sizebot needs to run, because we don't want to leak the token to
158+
# arbitrary code written by an outside contributor.
159+
#
160+
# This only affects PR branches. CI workflows that run on the main
161+
# branch are allowed to access environment variables, because only those
162+
# with push access can land code in main.
163+
#
164+
# As a temporary workaround, we'll fetch the assets from a mirror.
165+
# Need to figure out a longer term solution for this.
166+
#
167+
# Original code
168+
#
169+
# command: |
170+
# git fetch origin main
171+
# cd ./scripts/release && yarn && cd ../../
172+
# scripts/release/download-experimental-build.js --commit=$(git merge-base HEAD origin/main) --allowBrokenCI
173+
# mv ./build ./base-build
174+
#
175+
# Workaround. Fetch the artifacts from react-builds.vercel.app. This
176+
# is the same app that hosts the sizebot diff previews.
154177
command: |
155-
git fetch origin main
156-
cd ./scripts/release && yarn && cd ../../
157-
scripts/release/download-experimental-build.js --commit=$(git merge-base HEAD origin/main) --allowBrokenCI
178+
curl -L --retry 60 --retry-delay 10 --retry-max-time 600 https://react-builds.vercel.app/api/commits/$(git merge-base HEAD origin/main)/artifacts/build.tgz | tar -xz
158179
mv ./build ./base-build
180+
159181
- run:
160182
# TODO: The `download-experimental-build` script copies the npm
161183
# packages into the `node_modules` directory. This is a historical

.github/workflows/commit_artifacts.yml

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Commit Artifacts for Facebook WWW
1+
name: Commit Artifacts for Facebook WWW and fbsource
22

33
on:
44
push:
@@ -10,6 +10,8 @@ jobs:
1010
steps:
1111
- name: Download and unzip artifacts
1212
uses: actions/github-script@v6
13+
env:
14+
CIRCLECI_TOKEN: ${{secrets.CIRCLECI_TOKEN_DIFFTRAIN}}
1315
with:
1416
script: |
1517
const cp = require('child_process');
@@ -58,10 +60,10 @@ jobs:
5860
const ciBuildId = /\/facebook\/react\/([0-9]+)/.exec(
5961
status.target_url,
6062
)[1];
61-
console.log(`CircleCI build id found: ${ciBuildId}`);
6263
if (Number.parseInt(ciBuildId, 10) + '' === ciBuildId) {
6364
artifactsUrl =
6465
`https://circleci.com/api/v1.1/project/github/facebook/react/${ciBuildId}/artifacts`;
66+
console.log(`Found artifactsUrl: ${artifactsUrl}`);
6567
break spinloop;
6668
} else {
6769
throw new Error(`${ciBuildId} isn't a number`);
@@ -80,13 +82,21 @@ jobs:
8082
await sleep(60_000);
8183
}
8284
if (artifactsUrl != null) {
83-
const res = await fetch(artifactsUrl);
85+
const {CIRCLECI_TOKEN} = process.env;
86+
const res = await fetch(artifactsUrl, {
87+
headers: {
88+
'Circle-Token': CIRCLECI_TOKEN
89+
}
90+
});
8491
const data = await res.json();
92+
if (!Array.isArray(data) && data.message != null) {
93+
throw `CircleCI returned: ${data.message}`;
94+
}
8595
for (const artifact of data) {
8696
if (artifact.path === 'build.tgz') {
8797
console.log(`Downloading and unzipping ${artifact.url}`);
8898
await execHelper(
89-
`curl -L ${artifact.url} | tar -xvz`
99+
`curl -L ${artifact.url} -H "Circle-Token: ${CIRCLECI_TOKEN}" | tar -xvz`
90100
);
91101
}
92102
}
@@ -98,7 +108,7 @@ jobs:
98108
sed -i -e 's/ @license React*//' \
99109
build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
100110
build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js
101-
- name: Move relevant files into compiled
111+
- name: Move relevant files for React in www into compiled
102112
run: |
103113
mkdir -p ./compiled
104114
mkdir -p ./compiled/facebook-www
@@ -122,16 +132,41 @@ jobs:
122132
mv build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js \
123133
./compiled/babel-plugin-react-refresh/index.js
124134
135+
ls -R ./compiled
136+
- name: Move relevant files for React in fbsource into compiled-rn
137+
run: |
138+
BASE_FOLDER='compiled-rn/facebook-fbsource/xplat/js'
139+
mkdir -p ${BASE_FOLDER}/react-native-github/Libraries/Renderer/
140+
mkdir -p ${BASE_FOLDER}/RKJSModules/vendor/{scheduler,react,react-is,react-test-renderer}/
141+
142+
# Move React Native renderer
143+
mv build/react-native/implementations/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
144+
mv build/react-native/shims/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
145+
mv build/facebook-react-native/scheduler/cjs/ $BASE_FOLDER/RKJSModules/vendor/scheduler/
146+
mv build/facebook-react-native/react/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/
147+
mv build/facebook-react-native/react-is/cjs/ $BASE_FOLDER/RKJSModules/vendor/react-is/
148+
mv build/facebook-react-native/react-test-renderer/cjs/ $BASE_FOLDER/RKJSModules/vendor/react-test-renderer/
149+
150+
# Delete OSS renderer. OSS renderer is synced through internal script.
151+
RENDERER_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/implementations/
152+
rm $RENDERER_FOLDER/ReactFabric-{dev,prod,profiling}.js
153+
rm $RENDERER_FOLDER/ReactNativeRenderer-{dev,prod,profiling}.js
154+
125155
ls -R ./compiled
126156
- name: Add REVISION file
127157
run: |
128158
echo ${{ github.sha }} >> ./compiled/facebook-www/REVISION
159+
echo ${{ github.sha }} >> ./compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION
129160
- uses: actions/upload-artifact@v3
130161
with:
131162
name: compiled
132163
path: compiled/
164+
- uses: actions/upload-artifact@v3
165+
with:
166+
name: compiled-rn
167+
path: compiled-rn/
133168

134-
commit_artifacts:
169+
commit_www_artifacts:
135170
needs: download_artifacts
136171
runs-on: ubuntu-latest
137172
steps:
@@ -165,3 +200,29 @@ jobs:
165200
commit_user_name: ${{ github.actor }}
166201
commit_user_email: ${{ github.actor }}@users.noreply.github.com
167202
create_branch: true
203+
204+
commit_fbsource_artifacts:
205+
needs: download_artifacts
206+
runs-on: ubuntu-latest
207+
steps:
208+
- uses: actions/checkout@v3
209+
with:
210+
ref: main
211+
repository: facebook/react-fbsource-import
212+
token: ${{secrets.FBSOURCE_SYNC_PUSH_TOKEN}}
213+
- name: Ensure clean directory
214+
run: rm -rf compiled-rn
215+
- uses: actions/download-artifact@v3
216+
with:
217+
name: compiled-rn
218+
path: compiled-rn/
219+
- run: git status -u
220+
- name: Commit changes to branch
221+
uses: stefanzweifel/git-auto-commit-action@v4
222+
with:
223+
commit_message: |
224+
${{ github.event.head_commit.message }}
225+
226+
DiffTrain build for commit https://github.com/facebook/react/commit/${{ github.sha }}.
227+
commit_user_name: ${{ github.actor }}
228+
commit_user_email: ${{ github.actor }}@users.noreply.github.com

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@
3636
"@babel/preset-flow": "^7.10.4",
3737
"@babel/preset-react": "^7.10.4",
3838
"@babel/traverse": "^7.11.0",
39-
"@rollup/plugin-babel": "^5.3.1",
40-
"@rollup/plugin-commonjs": "^22.0.1",
41-
"@rollup/plugin-node-resolve": "^13.3.0",
42-
"@rollup/plugin-replace": "^4.0.0",
39+
"@rollup/plugin-babel": "^6.0.3",
40+
"@rollup/plugin-commonjs": "^24.0.1",
41+
"@rollup/plugin-node-resolve": "^15.0.1",
42+
"@rollup/plugin-replace": "^5.0.2",
4343
"abortcontroller-polyfill": "^1.7.5",
4444
"art": "0.10.1",
4545
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
@@ -65,8 +65,8 @@
6565
"eslint-plugin-react-internal": "link:./scripts/eslint-rules",
6666
"fbjs-scripts": "^3.0.1",
6767
"filesize": "^6.0.1",
68-
"flow-bin": "^0.201.0",
69-
"flow-remove-types": "^2.201.0",
68+
"flow-bin": "^0.202.0",
69+
"flow-remove-types": "^2.202.0",
7070
"glob": "^7.1.6",
7171
"glob-stream": "^6.1.0",
7272
"google-closure-compiler": "^20230206.0.0",
@@ -89,9 +89,9 @@
8989
"random-seed": "^0.3.0",
9090
"react-lifecycles-compat": "^3.0.4",
9191
"rimraf": "^3.0.0",
92-
"rollup": "^2.76.0",
92+
"rollup": "^3.17.1",
9393
"rollup-plugin-prettier": "^3.0.0",
94-
"rollup-plugin-strip-banner": "^2.0.0",
94+
"rollup-plugin-strip-banner": "^3.0.0",
9595
"semver": "^7.1.1",
9696
"targz": "^1.0.1",
9797
"through2": "^3.0.1",

packages/internal-test-utils/ReactInternalTestUtils.js

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,23 @@ async function waitForMicrotasks() {
2929
});
3030
}
3131

32-
export async function waitFor(expectedLog) {
32+
export async function waitFor(expectedLog, options) {
3333
assertYieldsWereCleared(SchedulerMock);
3434

3535
// Create the error object before doing any async work, to get a better
3636
// stack trace.
3737
const error = new Error();
3838
Error.captureStackTrace(error, waitFor);
3939

40+
const stopAfter = expectedLog.length;
4041
const actualLog = [];
4142
do {
4243
// Wait until end of current task/microtask.
4344
await waitForMicrotasks();
4445
if (SchedulerMock.unstable_hasPendingWork()) {
45-
SchedulerMock.unstable_flushNumberOfYields(
46-
expectedLog.length - actualLog.length,
47-
);
46+
SchedulerMock.unstable_flushNumberOfYields(stopAfter - actualLog.length);
4847
actualLog.push(...SchedulerMock.unstable_clearLog());
49-
if (expectedLog.length > actualLog.length) {
48+
if (stopAfter > actualLog.length) {
5049
// Continue flushing until we've logged the expected number of items.
5150
} else {
5251
// Once we've reached the expected sequence, wait one more microtask to
@@ -61,6 +60,12 @@ export async function waitFor(expectedLog) {
6160
}
6261
} while (true);
6362

63+
if (options && options.additionalLogsAfterAttemptingToYield) {
64+
expectedLog = expectedLog.concat(
65+
options.additionalLogsAfterAttemptingToYield,
66+
);
67+
}
68+
6469
if (equals(actualLog, expectedLog)) {
6570
return;
6671
}
@@ -151,6 +156,34 @@ ${diff(expectedError, x)}
151156
} while (true);
152157
}
153158

159+
// This is prefixed with `unstable_` because you should almost always try to
160+
// avoid using it in tests. It's really only for testing a particular
161+
// implementation detail (update starvation prevention).
162+
export async function unstable_waitForExpired(expectedLog): mixed {
163+
assertYieldsWereCleared(SchedulerMock);
164+
165+
// Create the error object before doing any async work, to get a better
166+
// stack trace.
167+
const error = new Error();
168+
Error.captureStackTrace(error, unstable_waitForExpired);
169+
170+
// Wait until end of current task/microtask.
171+
await waitForMicrotasks();
172+
SchedulerMock.unstable_flushExpired();
173+
174+
const actualLog = SchedulerMock.unstable_clearLog();
175+
if (equals(actualLog, expectedLog)) {
176+
return;
177+
}
178+
179+
error.message = `
180+
Expected sequence of events did not occur.
181+
182+
${diff(expectedLog, actualLog)}
183+
`;
184+
throw error;
185+
}
186+
154187
// TODO: This name is a bit misleading currently because it will stop as soon as
155188
// React yields for any reason, not just for a paint. I've left it this way for
156189
// now because that's how untable_flushUntilNextPaint already worked, but maybe
@@ -185,6 +218,30 @@ ${diff(expectedLog, actualLog)}
185218
throw error;
186219
}
187220

221+
export async function waitForDiscrete(expectedLog) {
222+
assertYieldsWereCleared(SchedulerMock);
223+
224+
// Create the error object before doing any async work, to get a better
225+
// stack trace.
226+
const error = new Error();
227+
Error.captureStackTrace(error, waitForDiscrete);
228+
229+
// Wait until end of current task/microtask.
230+
await waitForMicrotasks();
231+
232+
const actualLog = SchedulerMock.unstable_clearLog();
233+
if (equals(actualLog, expectedLog)) {
234+
return;
235+
}
236+
237+
error.message = `
238+
Expected sequence of events did not occur.
239+
240+
${diff(expectedLog, actualLog)}
241+
`;
242+
throw error;
243+
}
244+
188245
export function assertLog(expectedLog) {
189246
const actualLog = SchedulerMock.unstable_clearLog();
190247
if (equals(actualLog, expectedLog)) {

packages/internal-test-utils/__tests__/ReactInternalTestUtils-test.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,9 @@ describe('ReactInternalTestUtils', () => {
9999
assertLog([
100100
'A',
101101
'B',
102-
'C',
103-
'D',
104102
// React will try one more time before giving up.
105103
'A',
106104
'B',
107-
'C',
108-
'D',
109105
]);
110106
});
111107

packages/internal-test-utils/internalAct.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function act<T>(scope: () => Thenable<T>): Thenable<T> {
3535
);
3636
}
3737

38-
// $FlowFixMe: Flow doesn't know about global Jest object
38+
// $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object
3939
if (!jest.isMockFunction(setTimeout)) {
4040
throw Error(
4141
"This version of `act` requires Jest's timer mocks " +
@@ -70,7 +70,7 @@ export async function act<T>(scope: () => Thenable<T>): Thenable<T> {
7070
// Wait until end of current task/microtask.
7171
await waitForMicrotasks();
7272

73-
// $FlowFixMe: Flow doesn't know about global Jest object
73+
// $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object
7474
if (jest.isEnvironmentTornDown()) {
7575
error.message =
7676
'The Jest environment was torn down before `act` completed. This ' +
@@ -79,8 +79,20 @@ export async function act<T>(scope: () => Thenable<T>): Thenable<T> {
7979
}
8080

8181
if (!Scheduler.unstable_hasPendingWork()) {
82-
// $FlowFixMe: Flow doesn't know about global Jest object
83-
jest.runOnlyPendingTimers();
82+
// $FlowFixMe[cannot-resolve-name]: Flow doesn't know about global Jest object
83+
const j = jest;
84+
if (j.getTimerCount() > 0) {
85+
// There's a pending timer. Flush it now. We only do this in order to
86+
// force Suspense fallbacks to display; the fact that it's a timer
87+
// is an implementation detail. If there are other timers scheduled,
88+
// those will also fire now, too, which is not ideal. (The public
89+
// version of `act` doesn't do this.) For this reason, we should try
90+
// to avoid using timers in our internal tests.
91+
j.runOnlyPendingTimers();
92+
// If a committing a fallback triggers another update, it might not
93+
// get scheduled until a microtask. So wait one more time.
94+
await waitForMicrotasks();
95+
}
8496
if (Scheduler.unstable_hasPendingWork()) {
8597
// Committing a fallback scheduled additional work. Continue flushing.
8698
} else {

packages/react-art/src/ReactARTHostConfig.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,22 @@ export function requestPostPaintCallback(callback: (time: number) => void) {
459459
// noop
460460
}
461461

462+
export function maySuspendCommit(type, props) {
463+
return false;
464+
}
465+
466+
export function preloadInstance(type, props) {
467+
// Return true to indicate it's already loaded
468+
return true;
469+
}
470+
471+
export function startSuspendingCommit() {}
472+
473+
export function suspendInstance(type, props) {}
474+
475+
export function waitForCommitToBeReady() {
476+
return null;
477+
}
462478
// eslint-disable-next-line no-undef
463479
export function prepareRendererToRender(container: Container): void {
464480
// noop

0 commit comments

Comments
 (0)