diff --git a/.eslintrc.js b/.eslintrc.js index 2aa48458b8..280f57221c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -303,7 +303,6 @@ module.exports = { ERROR, {isProductionUserAppCode: true}, ], - 'react-internal/no-to-warn-dev-within-to-throw': ERROR, 'react-internal/warning-args': ERROR, 'react-internal/no-production-logging': ERROR, }, @@ -590,6 +589,11 @@ module.exports = { WheelEventHandler: 'readonly', FinalizationRegistry: 'readonly', Omit: 'readonly', + Keyframe: 'readonly', + PropertyIndexedKeyframes: 'readonly', + KeyframeAnimationOptions: 'readonly', + GetAnimationsOptions: 'readonly', + Animatable: 'readonly', spyOnDev: 'readonly', spyOnDevAndProd: 'readonly', diff --git a/.github/workflows/compiler_playground.yml b/.github/workflows/compiler_playground.yml index 68d14a7661..d3d2420ee2 100644 --- a/.github/workflows/compiler_playground.yml +++ b/.github/workflows/compiler_playground.yml @@ -38,11 +38,7 @@ jobs: with: path: "**/node_modules" key: compiler-node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('compiler/**/yarn.lock') }} - - name: yarn install compiler - run: yarn install --frozen-lockfile - working-directory: compiler - - name: yarn install playground - run: yarn install --frozen-lockfile + - run: yarn install --frozen-lockfile - run: npx playwright install --with-deps chromium - run: CI=true yarn test - run: ls -R test-results diff --git a/.github/workflows/shared_discord_notify.yml b/.github/workflows/shared_discord_notify.yml new file mode 100644 index 0000000000..86fd28af3b --- /dev/null +++ b/.github/workflows/shared_discord_notify.yml @@ -0,0 +1,21 @@ +name: (Shared) Discord Notify + +on: + pull_request_target: + types: [labeled] + +jobs: + notify: + if: ${{ github.event.label.name == 'React Core Team' }} + runs-on: ubuntu-latest + steps: + - name: Discord Webhook Action + uses: tsickert/discord-webhook@v6.0.0 + with: + webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} + embed-author-name: ${{ github.event.pull_request.user.login }} + embed-author-url: ${{ github.event.pull_request.user.html_url }} + embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }} + embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}' + embed-description: ${{ github.event.pull_request.body }} + embed-url: ${{ github.event.pull_request.html_url }} diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-all-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-all-output.txt new file mode 100644 index 0000000000..5633cf0b0f --- /dev/null +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-all-output.txt @@ -0,0 +1,13 @@ +import { c as _c } from "react/compiler-runtime"; // + @compilationMode(all) +function nonReactFn() { + const $ = _c(1); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = {}; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-infer-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-infer-output.txt new file mode 100644 index 0000000000..b50c37fc4e --- /dev/null +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-infer-output.txt @@ -0,0 +1,4 @@ +// @compilationMode(infer) +function nonReactFn() { + return {}; +} \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/page.spec.ts b/compiler/apps/playground/__tests__/e2e/page.spec.ts index 05fe96d4b9..3ba082cf62 100644 --- a/compiler/apps/playground/__tests__/e2e/page.spec.ts +++ b/compiler/apps/playground/__tests__/e2e/page.spec.ts @@ -79,6 +79,24 @@ function Foo() { // @flow function useFoo(propVal: {+baz: number}) { return
Error
'); + }, + onError(x) { + didError = true; + console.error(x); + }, + } + ); + // Abandon and switch to client rendering after 5 seconds. + // Try lowering this to see the client recover. + setTimeout(abort, 5000); +} diff --git a/fixtures/view-transition/src/components/App.js b/fixtures/view-transition/src/components/App.js new file mode 100644 index 0000000000..028f511107 --- /dev/null +++ b/fixtures/view-transition/src/components/App.js @@ -0,0 +1,79 @@ +import React, { + startTransition, + useLayoutEffect, + useEffect, + useState, +} from 'react'; + +import Chrome from './Chrome'; +import Page from './Page'; + +const enableNavigationAPI = typeof navigation === 'object'; + +export default function App({assets, initialURL}) { + const [routerState, setRouterState] = useState({ + pendingNav: () => {}, + url: initialURL, + }); + function navigate(url) { + if (enableNavigationAPI) { + window.navigation.navigate(url); + } else { + startTransition(() => { + setRouterState({ + url, + pendingNav() { + window.history.pushState({}, '', url); + }, + }); + }); + } + } + useEffect(() => { + if (enableNavigationAPI) { + window.navigation.addEventListener('navigate', event => { + if (!event.canIntercept) { + return; + } + const newURL = new URL(event.destination.url); + event.intercept({ + handler() { + let promise; + startTransition(() => { + promise = new Promise(resolve => { + setRouterState({ + url: newURL.pathname + newURL.search, + pendingNav: resolve, + }); + }); + }); + return promise; + }, + commit: 'after-transition', // plz ship this, browsers + }); + }); + } else { + window.addEventListener('popstate', () => { + // This should not animate because restoration has to be synchronous. + // Even though it's a transition. + startTransition(() => { + setRouterState({ + url: document.location.pathname + document.location.search, + pendingNav() { + // Noop. URL has already updated. + }, + }); + }); + }); + } + }, []); + const pendingNav = routerState.pendingNav; + useLayoutEffect(() => { + pendingNav(); + }, [pendingNav]); + return ( +