Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read constructor name more carefully #29954

Merged
merged 4 commits into from
Jun 25, 2024
Merged
Changes from 1 commit
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
Next Next commit
Read constructor name more carefully
Sometimes `constructor` happens to be the name of an unrelated property, or we may be dealing with a `Proxy` that intercepts every read. Verify the constructor is a function before using its name, and reset the name anyway if it turns out not to be serializable.

Fixes some cases of the devtools crashing and becoming inoperable upon attempting to inspect components whose props are Hookstate `State`s.
  • Loading branch information
LoganDark authored Jun 19, 2024
commit c01e1a6e0f0658ff0da7c9bbbdd4e7b9fe8c0e71
24 changes: 21 additions & 3 deletions packages/react-devtools-shared/src/hydration.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,17 @@ function createDehydrated(
preview_long: formatDataForPreview(data, true),
preview_short: formatDataForPreview(data, false),
name:
!data.constructor || data.constructor.name === 'Object'
typeof data.constructor !== 'function' || data.constructor.name === 'Object'
? ''
: data.constructor.name,
};

try {
structuredClone(dehydrated.name);
} catch (_) {
dehydrated.name = '';
}

if (type === 'array' || type === 'typed_array') {
dehydrated.size = data.length;
} else if (type === 'object') {
Expand Down Expand Up @@ -240,11 +246,17 @@ export function dehydrate(
preview_short: formatDataForPreview(data, false),
preview_long: formatDataForPreview(data, true),
name:
!data.constructor || data.constructor.name === 'Object'
typeof data.constructor !== 'function' || data.constructor.name === 'Object'
? ''
: data.constructor.name,
};

try {
structuredClone(unserializableValue.name);
} catch (_) {
unserializableValue.name = '';
}

// TRICKY
// Don't use [...spread] syntax for this purpose.
// This project uses @babel/plugin-transform-spread in "loose" mode which only works with Array values.
Expand Down Expand Up @@ -332,9 +344,15 @@ export function dehydrate(
readonly: true,
preview_short: formatDataForPreview(data, false),
preview_long: formatDataForPreview(data, true),
name: data.constructor.name,
name: typeof data.constructor === 'function' ? data.constructor.name : '',
};

try {
structuredClone(value.name);
} catch (_) {
value.name = '';
}

getAllEnumerableKeys(data).forEach(key => {
const keyAsString = key.toString();

Expand Down