Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 13 additions & 31 deletions packages/react-client/src/ReactFlightClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import type {TemporaryReferenceSet} from './ReactFlightTemporaryReferences';
import {
enablePostpone,
enableOwnerStacks,
enableServerComponentLogs,
enableProfilerTimer,
enableComponentPerformanceTrack,
} from 'shared/ReactFeatureFlags';
Expand Down Expand Up @@ -2139,34 +2138,22 @@ function resolveErrorDev(
}

let error;
if (!enableOwnerStacks && !enableServerComponentLogs) {
// Executing Error within a native stack isn't really limited to owner stacks
// but we gate it behind the same flag for now while iterating.
// eslint-disable-next-line react-internal/prod-error-codes
error = Error(
const callStack = buildFakeCallStack(
response,
stack,
env,
// $FlowFixMe[incompatible-use]
Error.bind(
null,
message ||
'An error occurred in the Server Components render but no message was provided',
);
// For backwards compat we use the V8 formatting when the flag is off.
error.stack = formatV8Stack(error.name, error.message, stack);
),
);
const rootTask = getRootTask(response, env);
if (rootTask != null) {
error = rootTask.run(callStack);
} else {
const callStack = buildFakeCallStack(
response,
stack,
env,
// $FlowFixMe[incompatible-use]
Error.bind(
null,
message ||
'An error occurred in the Server Components render but no message was provided',
),
);
const rootTask = getRootTask(response, env);
if (rootTask != null) {
error = rootTask.run(callStack);
} else {
error = callStack();
}
error = callStack();
}

(error: any).environmentName = env;
Expand Down Expand Up @@ -2699,11 +2686,6 @@ function resolveConsoleEntry(
const env = payload[3];
const args = payload.slice(4);

if (!enableOwnerStacks && !enableServerComponentLogs) {
bindToConsole(methodName, args, env)();
return;
}

replayConsoleWithCallStackInDEV(
response,
methodName,
Expand Down
67 changes: 23 additions & 44 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1377,26 +1377,14 @@ describe('ReactFlight', () => {
errors: [
{
message: 'This is an error',
stack: gate(
flags =>
flags.enableOwnerStacks || flags.enableServerComponentLogs,
)
? expect.stringContaining(
'Error: This is an error\n' +
' at eval (eval at testFunction (inspected-page.html:29:11),%20%3Canonymous%3E:1:35)\n' +
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
' at <anonymous> (file:///testing.js:42:3)\n' +
' at <anonymous> (file:///testing.js:42:3)\n' +
' at div (<anonymous>',
)
: expect.stringContaining(
'Error: This is an error\n' +
' at eval (eval at testFunction (inspected-page.html:29:11),%20%3Canonymous%3E:1:10)\n' +
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
' at file:///testing.js:42:3\n' +
' at file:///testing.js:42:3\n' +
' at div (<anonymous>',
),
stack: expect.stringContaining(
'Error: This is an error\n' +
' at eval (eval at testFunction (inspected-page.html:29:11),%20%3Canonymous%3E:1:35)\n' +
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
' at <anonymous> (file:///testing.js:42:3)\n' +
' at <anonymous> (file:///testing.js:42:3)\n' +
' at div (<anonymous>',
),
digest: 'a dev digest',
environmentName: 'Server',
},
Expand All @@ -1415,18 +1403,16 @@ describe('ReactFlight', () => {
['', 'Server'],
[__filename, 'Server'],
]
: gate(flags => flags.enableServerComponentLogs)
? [
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
['inspected-page.html:29:11), <anonymous>', 'Server'],
[
'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',
'Server',
],
['file:///testing.js', 'Server'],
['', 'Server'],
]
: [],
: [
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
['inspected-page.html:29:11), <anonymous>', 'Server'],
[
'file://~/(some)(really)(exotic-directory)/ReactFlight-test.js',
'Server',
],
['file:///testing.js', 'Server'],
['', 'Server'],
],
});
} else {
expect(errors.map(getErrorForJestMatcher)).toEqual([
Expand Down Expand Up @@ -3312,14 +3298,7 @@ describe('ReactFlight', () => {
.split('\n')
.slice(0, 4)
.join('\n')
.replaceAll(
' (/',
gate(
flags => flags.enableOwnerStacks || flags.enableServerComponentLogs,
)
? ' (file:///'
: ' (/',
); // The eval will end up normalizing these
.replaceAll(' (/', ' (file:///'); // The eval will end up normalizing these

let sawReactPrefix = false;
const environments = [];
Expand Down Expand Up @@ -3352,7 +3331,7 @@ describe('ReactFlight', () => {
'third-party',
'third-party',
]);
} else if (__DEV__ && gate(flags => flags.enableServerComponentLogs)) {
} else if (__DEV__) {
expect(environments.slice(0, 3)).toEqual([
'third-party',
'third-party',
Expand Down Expand Up @@ -3412,7 +3391,7 @@ describe('ReactFlight', () => {
expect(ReactNoop).toMatchRenderedOutput(<div>hi</div>);
});

// @gate enableServerComponentLogs && __DEV__ && enableOwnerStacks
// @gate __DEV__ && enableOwnerStacks
it('replays logs, but not onError logs', async () => {
function foo() {
return 'hello';
Expand Down Expand Up @@ -3493,7 +3472,7 @@ describe('ReactFlight', () => {
expect(ownerStacks).toEqual(['\n in App (at **)']);
});

// @gate enableServerComponentLogs && __DEV__
// @gate __DEV__
it('replays logs with cyclic objects', async () => {
const cyclic = {cycle: null};
cyclic.cycle = cyclic;
Expand Down Expand Up @@ -3764,7 +3743,7 @@ describe('ReactFlight', () => {
);
});

// @gate (enableOwnerStacks && enableServerComponentLogs) || !__DEV__
// @gate (enableOwnerStacks) || !__DEV__
it('should include only one component stack in replayed logs (if DevTools or polyfill adds them)', () => {
class MyError extends Error {
toJSON() {
Expand Down
27 changes: 9 additions & 18 deletions packages/react-dom-bindings/src/client/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -2510,26 +2510,17 @@ function diffHydratedGenericElement(
);
}
}
hydrateSanitizedAttribute(
domElement,
propKey,
propKey,
null,
extraAttributes,
serverDifferences,
);
continue;
} else {
hydrateSanitizedAttribute(
domElement,
propKey,
propKey,
value,
extraAttributes,
serverDifferences,
);
continue;
}
hydrateSanitizedAttribute(
domElement,
propKey,
propKey,
value,
extraAttributes,
serverDifferences,
);
continue;
case 'action':
case 'formAction': {
const serverValue = domElement.getAttribute(propKey);
Expand Down
6 changes: 4 additions & 2 deletions packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,9 @@ export function canHydrateInstance(
} else if (
rel !== anyProps.rel ||
element.getAttribute('href') !==
(anyProps.href == null ? null : anyProps.href) ||
(anyProps.href == null || anyProps.href === ''
? null
: anyProps.href) ||
element.getAttribute('crossorigin') !==
(anyProps.crossOrigin == null ? null : anyProps.crossOrigin) ||
element.getAttribute('title') !==
Expand Down Expand Up @@ -2984,7 +2986,7 @@ export function hydrateHoistable(
const node = nodes[i];
if (
node.getAttribute('href') !==
(props.href == null ? null : props.href) ||
(props.href == null || props.href === '' ? null : props.href) ||
node.getAttribute('rel') !==
(props.rel == null ? null : props.rel) ||
node.getAttribute('title') !==
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,23 @@ describe('ReactDOMServerIntegration', () => {
expect(e.getAttribute('href')).toBe('');
});

itRenders('empty href on other tags', async render => {
itRenders('empty href on base tags as null', async render => {
const e = await render(<base href="" />, 1);
expect(e.getAttribute('href')).toBe(null);
});

itRenders('empty href on area tags as null', async render => {
const e = await render(
// <link href="" /> would be more sensible.
// However, that results in a hydration warning as well.
// Our test helpers do not support different error counts for initial
// server render and hydration.
// The number of errors on the server need to be equal to the number of
// errors during hydration.
// So we use a <div> instead.
<div href="" />,
<map>
<area alt="" href="" />
</map>,
1,
);
expect(e.firstChild.getAttribute('href')).toBe(null);
});

itRenders('empty href on link tags as null', async render => {
const e = await render(<link rel="stylesheet" href="" />, 1);
expect(e.getAttribute('href')).toBe(null);
});

Expand Down
8 changes: 1 addition & 7 deletions packages/react-server/src/ReactFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
enablePostpone,
enableHalt,
enableTaint,
enableServerComponentLogs,
enableOwnerStacks,
enableProfilerTimer,
enableComponentPerformanceTrack,
Expand Down Expand Up @@ -234,12 +233,7 @@ function patchConsole(consoleInst: typeof console, methodName: string) {
}
}

if (
enableServerComponentLogs &&
__DEV__ &&
typeof console === 'object' &&
console !== null
) {
if (__DEV__ && typeof console === 'object' && console !== null) {
// Instrument console to capture logs for replaying on the client.
patchConsole(console, 'assert');
patchConsole(console, 'debug');
Expand Down
2 changes: 0 additions & 2 deletions packages/shared/ReactFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ export const alwaysThrottleRetries = true;

export const passChildrenWhenCloningPersistedNodes = false;

export const enableServerComponentLogs = true;

/**
* Enables a new Fiber flag used in persisted mode to reduce the number
* of cloned host components.
Expand Down
1 change: 0 additions & 1 deletion packages/shared/forks/ReactFeatureFlags.native-fb.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export const enableRetryLaneExpiration = false;
export const enableSchedulingProfiler = __PROFILE__;
export const enableComponentPerformanceTrack = false;
export const enableScopeAPI = false;
export const enableServerComponentLogs = true;
export const enableSuspenseAvoidThisFallback = false;
export const enableSuspenseCallback = true;
export const enableTaint = true;
Expand Down
1 change: 0 additions & 1 deletion packages/shared/forks/ReactFeatureFlags.native-oss.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export const enableRetryLaneExpiration = false;
export const enableSchedulingProfiler = __PROFILE__;
export const enableComponentPerformanceTrack = false;
export const enableScopeAPI = false;
export const enableServerComponentLogs = true;
export const enableShallowPropDiffing = false;
export const enableSuspenseAvoidThisFallback = false;
export const enableSuspenseCallback = false;
Expand Down
1 change: 0 additions & 1 deletion packages/shared/forks/ReactFeatureFlags.test-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export const passChildrenWhenCloningPersistedNodes = false;
export const enablePersistedModeClonedFlag = false;
export const disableClientCache = true;

export const enableServerComponentLogs = true;
export const enableInfiniteRenderLoopDetection = false;

export const renameElementSymbol = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export const enableRetryLaneExpiration = false;
export const enableSchedulingProfiler = __PROFILE__;
export const enableComponentPerformanceTrack = false;
export const enableScopeAPI = false;
export const enableServerComponentLogs = true;
export const enableShallowPropDiffing = false;
export const enableSuspenseAvoidThisFallback = false;
export const enableSuspenseCallback = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export const passChildrenWhenCloningPersistedNodes = false;
export const enablePersistedModeClonedFlag = false;
export const disableClientCache = true;

export const enableServerComponentLogs = true;
export const enableInfiniteRenderLoopDetection = false;

export const enableReactTestRendererWarning = false;
Expand Down
2 changes: 0 additions & 2 deletions packages/shared/forks/ReactFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ export const enablePersistedModeClonedFlag = false;
export const enableAsyncDebugInfo = false;
export const disableClientCache = true;

export const enableServerComponentLogs = true;

export const enableReactTestRendererWarning = false;

export const disableLegacyMode = true;
Expand Down
Loading