mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Update test and stack frame code to support newer V8 stack formats (#22477)
This commit is contained in:
@@ -168,7 +168,15 @@ export function describeNativeComponentFrame(
|
||||
// The next one that isn't the same should be our match though.
|
||||
if (c < 0 || sampleLines[s] !== controlLines[c]) {
|
||||
// V8 adds a "new" prefix for native classes. Let's remove it to make it prettier.
|
||||
const frame = '\n' + sampleLines[s].replace(' at new ', ' at ');
|
||||
let frame = '\n' + sampleLines[s].replace(' at new ', ' at ');
|
||||
|
||||
// If our component frame is labeled "<anonymous>"
|
||||
// but we have a user-provided "displayName"
|
||||
// splice it in to make the stack more readable.
|
||||
if (fn.displayName && frame.includes('<anonymous>')) {
|
||||
frame = frame.replace('<anonymous>', fn.displayName);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
if (typeof fn === 'function') {
|
||||
componentFrameCache.set(fn, frame);
|
||||
|
||||
50
scripts/jest/matchers/toThrow.js
Normal file
50
scripts/jest/matchers/toThrow.js
Normal file
@@ -0,0 +1,50 @@
|
||||
'use strict';
|
||||
|
||||
// V8 uses a different message format when reading properties of null or undefined.
|
||||
// Older versions use e.g. "Cannot read property 'world' of undefined"
|
||||
// Newer versions use e.g. "Cannot read properties of undefined (reading 'world')"
|
||||
// This file overrides the built-in toThrow() matches to handle both cases,
|
||||
// enabling the React project to support Node 12-16 witout forking tests.
|
||||
|
||||
const toThrowMatchers = require('expect/build/toThrowMatchers').default;
|
||||
const builtInToThrow = toThrowMatchers.toThrow;
|
||||
|
||||
// Detect the newer stack format:
|
||||
let newErrorFormat = false;
|
||||
try {
|
||||
null.test();
|
||||
} catch (error) {
|
||||
if (error.message.includes('Cannot read properties of null')) {
|
||||
newErrorFormat = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect the message pattern we need to rename:
|
||||
const regex = /Cannot read property '([^']+)' of (.+)/;
|
||||
|
||||
// Massage strings (written in the older format) to match the newer format
|
||||
// if tests are currently running on Node 16+
|
||||
function normalizeErrorMessage(message) {
|
||||
if (newErrorFormat) {
|
||||
const match = message.match(regex);
|
||||
if (match) {
|
||||
return `Cannot read properties of ${match[2]} (reading '${match[1]}')`;
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
function toThrow(value, expectedValue) {
|
||||
if (typeof expectedValue === 'string') {
|
||||
expectedValue = normalizeErrorMessage(expectedValue);
|
||||
} else if (expectedValue instanceof Error) {
|
||||
expectedValue.message = normalizeErrorMessage(expectedValue.message);
|
||||
}
|
||||
|
||||
return builtInToThrow.call(this, value, expectedValue);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
toThrow,
|
||||
};
|
||||
@@ -45,8 +45,9 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
|
||||
}
|
||||
|
||||
expect.extend({
|
||||
...require('./matchers/toWarnDev'),
|
||||
...require('./matchers/reactTestMatchers'),
|
||||
...require('./matchers/toThrow'),
|
||||
...require('./matchers/toWarnDev'),
|
||||
});
|
||||
|
||||
// We have a Babel transform that inserts guards against infinite loops.
|
||||
|
||||
@@ -46,8 +46,9 @@ global.spyOnProd = function(...args) {
|
||||
};
|
||||
|
||||
expect.extend({
|
||||
...require('../matchers/toWarnDev'),
|
||||
...require('../matchers/reactTestMatchers'),
|
||||
...require('../matchers/toThrow'),
|
||||
...require('../matchers/toWarnDev'),
|
||||
});
|
||||
|
||||
beforeEach(() => (numExpectations = 0));
|
||||
|
||||
Reference in New Issue
Block a user