Skip to content
Open
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
57 changes: 40 additions & 17 deletions packages/shared/ReactPerformanceTrackProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
* @flow
*/

import {OMITTED_PROP_ERROR} from 'shared/ReactFlightPropertyAccess';
import { OMITTED_PROP_ERROR } from 'shared/ReactFlightPropertyAccess';

import hasOwnProperty from 'shared/hasOwnProperty';
import isArray from 'shared/isArray';
import {REACT_ELEMENT_TYPE} from './ReactSymbols';
import { REACT_ELEMENT_TYPE } from './ReactSymbols';
import getComponentNameFromType from './getComponentNameFromType';

const EMPTY_ARRAY = 0;
Expand Down Expand Up @@ -62,18 +62,36 @@ export function addObjectToProperties(
prefix: string,
): void {
let addedProperties = 0;
for (const key in object) {

// Collect keys safely — cross-origin objects (e.g. iframe.contentWindow)
// throw SecurityError on any property enumeration.
let keys: Array<string>;
try {
keys = [];
for (const key in object) {
keys.push(key);
}
} catch (e) {
// Cross-origin object: show a placeholder and bail out early.
properties.push([
prefix + '\xa0\xa0'.repeat(indent) + '[cross-origin object]',
'',
]);
return;
}

for (const key of keys) {
if (hasOwnProperty.call(object, key) && key[0] !== '_') {
addedProperties++;
const value = object[key];
addValueToProperties(key, value, properties, indent, prefix);
if (addedProperties >= OBJECT_WIDTH_LIMIT) {
properties.push([
prefix +
'\xa0\xa0'.repeat(indent) +
'Only ' +
OBJECT_WIDTH_LIMIT +
' properties are shown. React will not log more properties of this object.',
'\xa0\xa0'.repeat(indent) +
'Only ' +
OBJECT_WIDTH_LIMIT +
' properties are shown. React will not log more properties of this object.',
'',
]);
break;
Expand Down Expand Up @@ -245,9 +263,14 @@ export function addValueToProperties(
return;
}
if (objectName === 'Object') {
const proto: any = Object.getPrototypeOf(value);
if (proto && typeof proto.constructor === 'function') {
objectName = proto.constructor.name;
// Object.getPrototypeOf can throw SecurityError on cross-origin objects.
try {
const proto: any = Object.getPrototypeOf(value);
if (proto && typeof proto.constructor === 'function') {
objectName = proto.constructor.name;
}
} catch (e) {
// Cross-origin object — leave objectName as 'Object'.
}
}
properties.push([
Expand Down Expand Up @@ -310,8 +333,8 @@ export function addObjectDiffToProperties(
if (prevPropertiesChecked > OBJECT_WIDTH_LIMIT) {
properties.push([
'Previous object has more than ' +
OBJECT_WIDTH_LIMIT +
' properties. React will not attempt to diff objects with too many properties.',
OBJECT_WIDTH_LIMIT +
' properties. React will not attempt to diff objects with too many properties.',
'',
]);
isDeeplyEqual = false;
Expand All @@ -330,8 +353,8 @@ export function addObjectDiffToProperties(
if (nextPropertiesChecked > OBJECT_WIDTH_LIMIT) {
properties.push([
'Next object has more than ' +
OBJECT_WIDTH_LIMIT +
' properties. React will not attempt to diff objects with too many properties.',
OBJECT_WIDTH_LIMIT +
' properties. React will not attempt to diff objects with too many properties.',
'',
]);
isDeeplyEqual = false;
Expand Down Expand Up @@ -360,7 +383,7 @@ export function addObjectDiffToProperties(
prevValue !== null &&
nextValue !== null &&
readReactElementTypeof(prevValue) ===
readReactElementTypeof(nextValue)
readReactElementTypeof(nextValue)
) {
if (readReactElementTypeof(nextValue) === REACT_ELEMENT_TYPE) {
if (
Expand Down Expand Up @@ -431,7 +454,7 @@ export function addObjectDiffToProperties(
properties.push([
UNCHANGED + '\xa0\xa0'.repeat(indent) + key,
desc +
' Referentially unequal function closure. Consider memoization.',
' Referentially unequal function closure. Consider memoization.',
]);
continue;
}
Expand All @@ -450,4 +473,4 @@ export function addObjectDiffToProperties(
nextPropertiesChecked++;
}
return isDeeplyEqual;
}
}