Skip to content

Commit

Permalink
Merge branch 'main' into rdt-fusebox-expose-more-options
Browse files Browse the repository at this point in the history
  • Loading branch information
motiz88 committed May 3, 2024
2 parents a574fbc + 5fcfd71 commit f8c6e2d
Show file tree
Hide file tree
Showing 55 changed files with 620 additions and 268 deletions.
7 changes: 7 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,13 @@ jobs:
command: ./scripts/circleci/pack_and_store_devtools_artifacts.sh
- store_artifacts:
path: ./build/devtools.tgz
# Simplifies getting the extension for local testing
- store_artifacts:
path: ./build/devtools/chrome-extension.zip
destination: react-devtools-chrome-extension.zip
- store_artifacts:
path: ./build/devtools/firefox-extension.zip
destination: react-devtools-firefox-extension.zip

run_devtools_e2e_tests:
docker: *docker
Expand Down
36 changes: 0 additions & 36 deletions .github/workflows/commit_artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,42 +210,6 @@ jobs:
commit_user_email: ${{ github.actor }}@users.noreply.github.com
create_branch: true

commit_fbsource_artifacts_external_repo:
needs: download_artifacts
runs-on: ubuntu-latest
if: ${{ (github.ref == 'refs/heads/main' && needs.download_artifacts.outputs.fbsource_branch_count == '0') || github.ref == 'refs/heads/meta-fbsource' }}
steps:
- uses: actions/checkout@v4
with:
ref: main
repository: facebook/react-fbsource-import
token: ${{secrets.FBSOURCE_SYNC_PUSH_TOKEN}}
- name: Ensure clean directory
run: rm -rf compiled-rn
- uses: actions/download-artifact@v3
with:
name: compiled-rn
path: compiled-rn/
- run: git status -u
- name: Check if only the REVISION file has changed
id: check_should_commit
run: |
if git status --porcelain | grep -qv '/REVISION$'; then
echo "should_commit=true" >> "$GITHUB_OUTPUT"
else
echo "should_commit=false" >> "$GITHUB_OUTPUT"
fi
- name: Commit changes to branch
if: steps.check_should_commit.outputs.should_commit == 'true'
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: |
${{ github.event.head_commit.message }}
DiffTrain build for commit https://github.com/facebook/react/commit/${{ github.sha }}.
commit_user_name: ${{ github.actor }}
commit_user_email: ${{ github.actor }}@users.noreply.github.com

commit_fbsource_artifacts:
needs: download_artifacts
if: ${{ (github.ref == 'refs/heads/main' && needs.download_artifacts.outputs.fbsource_branch_count == '0') || github.ref == 'refs/heads/meta-fbsource' }}
Expand Down
2 changes: 2 additions & 0 deletions dangerfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ const CRITICAL_ARTIFACT_PATHS = new Set([
// We always report changes to these bundles, even if the change is
// insignificant or non-existent.
'oss-stable/react-dom/cjs/react-dom.production.js',
'oss-stable/react-dom/cjs/react-dom-client.production.js',
'oss-experimental/react-dom/cjs/react-dom.production.js',
'oss-experimental/react-dom/cjs/react-dom-client.production.js',
'facebook-www/ReactDOM-prod.classic.js',
'facebook-www/ReactDOM-prod.modern.js',
]);
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"through2": "^3.0.1",
"tmp": "^0.1.0",
"typescript": "^3.7.5",
"undici": "^5.28.4",
"web-streams-polyfill": "^3.1.1",
"yargs": "^15.3.1"
},
Expand All @@ -108,7 +109,7 @@
},
"scripts": {
"build": "node ./scripts/rollup/build-all-release-channels.js",
"build-for-devtools": "cross-env RELEASE_CHANNEL=experimental yarn build react/index,react/jsx,react-dom/index,react-dom/unstable_testing,react-dom/test-utils,react-is,react-debug-tools,scheduler,react-test-renderer,react-refresh,react-art --type=NODE",
"build-for-devtools": "cross-env RELEASE_CHANNEL=experimental yarn build react/index,react/jsx,react-dom/index,react-dom/client,react-dom/unstable_testing,react-dom/test-utils,react-is,react-debug-tools,scheduler,react-test-renderer,react-refresh,react-art --type=NODE",
"build-for-devtools-dev": "yarn build-for-devtools --type=NODE_DEV",
"build-for-devtools-prod": "yarn build-for-devtools --type=NODE_PROD",
"linc": "node ./scripts/tasks/linc.js",
Expand Down
20 changes: 17 additions & 3 deletions packages/react-client/src/ReactFlightReplyClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,17 @@ export function processReply(

function serializeTypedArray(
tag: string,
typedArray: ArrayBuffer | $ArrayBufferView,
typedArray: $ArrayBufferView,
): string {
const blob = new Blob([typedArray]);
const blob = new Blob([
// We should be able to pass the buffer straight through but Node < 18 treat
// multi-byte array blobs differently so we first convert it to single-byte.
new Uint8Array(
typedArray.buffer,
typedArray.byteOffset,
typedArray.byteLength,
),
]);
const blobId = nextPartId++;
if (formData === null) {
formData = new FormData();
Expand Down Expand Up @@ -392,7 +400,13 @@ export function processReply(

if (enableBinaryFlight) {
if (value instanceof ArrayBuffer) {
return serializeTypedArray('A', value);
const blob = new Blob([value]);
const blobId = nextPartId++;
if (formData === null) {
formData = new FormData();
}
formData.append(formFieldPrefix + blobId, blob);
return '$' + 'A' + blobId.toString(16);
}
if (value instanceof Int8Array) {
// char
Expand Down
62 changes: 34 additions & 28 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@

'use strict';

if (typeof Blob === 'undefined') {
global.Blob = require('buffer').Blob;
}
if (typeof File === 'undefined' || typeof FormData === 'undefined') {
global.File = require('undici').File;
global.FormData = require('undici').FormData;
}

function normalizeCodeLocInfo(str) {
return (
str &&
Expand Down Expand Up @@ -513,39 +521,37 @@ describe('ReactFlight', () => {
`);
});

if (typeof FormData !== 'undefined') {
it('can transport FormData (no blobs)', async () => {
function ComponentClient({prop}) {
return `
formData: ${prop instanceof FormData}
hi: ${prop.get('hi')}
multiple: ${prop.getAll('multiple')}
content: ${JSON.stringify(Array.from(prop))}
`;
}
const Component = clientReference(ComponentClient);

const formData = new FormData();
formData.append('hi', 'world');
formData.append('multiple', 1);
formData.append('multiple', 2);
it('can transport FormData (no blobs)', async () => {
function ComponentClient({prop}) {
return `
formData: ${prop instanceof FormData}
hi: ${prop.get('hi')}
multiple: ${prop.getAll('multiple')}
content: ${JSON.stringify(Array.from(prop))}
`;
}
const Component = clientReference(ComponentClient);

const model = <Component prop={formData} />;
const formData = new FormData();
formData.append('hi', 'world');
formData.append('multiple', 1);
formData.append('multiple', 2);

const transport = ReactNoopFlightServer.render(model);
const model = <Component prop={formData} />;

await act(async () => {
ReactNoop.render(await ReactNoopFlightClient.read(transport));
});
const transport = ReactNoopFlightServer.render(model);

expect(ReactNoop).toMatchRenderedOutput(`
formData: true
hi: world
multiple: 1,2
content: [["hi","world"],["multiple","1"],["multiple","2"]]
`);
await act(async () => {
ReactNoop.render(await ReactNoopFlightClient.read(transport));
});
}

expect(ReactNoop).toMatchRenderedOutput(`
formData: true
hi: world
multiple: 1,2
content: [["hi","world"],["multiple","1"],["multiple","2"]]
`);
});

it('can transport cyclic objects', async () => {
function ComponentClient({prop}) {
Expand Down
21 changes: 13 additions & 8 deletions packages/react-debug-tools/src/ReactDebugHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,20 @@ function readContext<T>(context: ReactContext<T>): T {
);
}

let value: T;
// For now we don't expose readContext usage in the hooks debugging info.
const value = hasOwnProperty.call(currentContextDependency, 'memoizedValue')
? // $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
((currentContextDependency.memoizedValue: any): T)
: // Before React 18, we did not have `memoizedValue` so we rely on `setupContexts` in those versions.
// $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
((currentContextDependency.context._currentValue: any): T);
// $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
currentContextDependency = currentContextDependency.next;
if (hasOwnProperty.call(currentContextDependency, 'memoizedValue')) {
// $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
value = ((currentContextDependency.memoizedValue: any): T);

// $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
currentContextDependency = currentContextDependency.next;
} else {
// Before React 18, we did not have `memoizedValue` so we rely on `setupContexts` in those versions.
// Multiple reads of the same context were also only tracked as a single dependency.
// We just give up on advancing context dependencies and solely rely on `setupContexts`.
value = context._currentValue;
}

return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('ReactHooksInspectionIntegration', () => {
ReactDOM = require('react-dom');
act = require('internal-test-utils').act;
ReactDebugTools = require('react-debug-tools');
useMemoCache = React.unstable_useMemoCache;
useMemoCache = require('react/compiler-runtime').c;
});

it('should inspect the current state of useState hooks', async () => {
Expand Down Expand Up @@ -833,6 +833,45 @@ describe('ReactHooksInspectionIntegration', () => {
`);
});

// @reactVersion >= 16.8
it('should inspect the value of the current provider in useContext reading the same context multiple times', async () => {
const ContextA = React.createContext('default A');
const ContextB = React.createContext('default B');
function Foo(props) {
React.useContext(ContextA);
React.useContext(ContextA);
React.useContext(ContextB);
React.useContext(ContextB);
React.useContext(ContextA);
React.useContext(ContextB);
React.useContext(ContextB);
React.useContext(ContextB);
return null;
}
let renderer;
await act(() => {
renderer = ReactTestRenderer.create(
<ContextA.Provider value="contextual A">
<Foo prop="prop" />
</ContextA.Provider>,
{unstable_isConcurrent: true},
);
});
const childFiber = renderer.root.findByType(Foo)._currentFiber();
const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);

expect(normalizeSourceLoc(tree)).toEqual([
expect.objectContaining({value: 'contextual A'}),
expect.objectContaining({value: 'contextual A'}),
expect.objectContaining({value: 'default B'}),
expect.objectContaining({value: 'default B'}),
expect.objectContaining({value: 'contextual A'}),
expect.objectContaining({value: 'default B'}),
expect.objectContaining({value: 'default B'}),
expect.objectContaining({value: 'default B'}),
]);
});

it('should inspect forwardRef', async () => {
const obj = function () {};
const Foo = React.forwardRef(function (props, ref) {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-devtools-extensions/webpack.backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ module.exports = {
__DEV__: true,
__PROFILE__: false,
__DEV____DEV__: true,
// By importing `shared/` we may import ReactFeatureFlags
__EXPERIMENTAL__: true,
'process.env.DEVTOOLS_PACKAGE': `"react-devtools-extensions"`,
'process.env.DEVTOOLS_VERSION': `"${DEVTOOLS_VERSION}"`,
'process.env.GITHUB_URL': `"${GITHUB_URL}"`,
Expand Down
21 changes: 15 additions & 6 deletions packages/react-devtools-fusebox/src/frontend.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@
* LICENSE file in the root directory of this source tree.
*/

export type MessagePayload = null | string | number | boolean | { [key: string]: MessagePayload } | MessagePayload[];
export type Message = { event: string, payload?: MessagePayload };
export type MessagePayload =
| null
| string
| number
| boolean
| {[key: string]: MessagePayload}
| MessagePayload[];
export type Message = {event: string; payload?: MessagePayload};

export type WallListener = (message: Message) => void;
export type Wall = {
listen: (fn: WallListener) => Function,
send: (event: string, payload?: MessagePayload) => void,
listen: (fn: WallListener) => Function;
send: (event: string, payload?: MessagePayload) => void;
};

export type Bridge = {
shutdown: () => void,
shutdown: () => void;
};
export type Store = Object;
export type BrowserTheme = 'dark' | 'light';
Expand Down Expand Up @@ -50,4 +56,7 @@ export type InitializationOptions = {
canViewElementSourceFunction?: CanViewElementSource,
};

export function initialize(node: Element | Document, options: InitializationOptions): void;
export function initialize(
node: Element | Document,
options: InitializationOptions,
): void;
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as React from 'react';
import {c as useMemoCache} from 'react/compiler-runtime';

export default function UseMemoCache(): React.Node {
React.unstable_useMemoCache(1);
useMemoCache(1);

return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ function extractEvents(
const temp = submitter.ownerDocument.createElement('input');
temp.name = submitter.name;
temp.value = submitter.value;
if (form.id) {
temp.setAttribute('form', form.id);
}
(submitter.parentNode: any).insertBefore(temp, submitter);
formData = new FormData(form);
(temp.parentNode: any).removeChild(temp);
Expand Down
Loading

0 comments on commit f8c6e2d

Please sign in to comment.