diff --git a/CHANGELOG.md b/CHANGELOG.md index 0170f3b6c9..dc47c11743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ - Performance Tracing should be disabled by default ([#3533](https://github.com/getsentry/sentry-react-native/pull/3533)) - Use `$NODE_BINARY` to execute Sentry CLI in Xcode scripts ([#3493](https://github.com/getsentry/sentry-react-native/pull/3493)) - Return auto Release and Dist to source maps auto upload ([#3540](https://github.com/getsentry/sentry-react-native/pull/3540)) +- Linked errors processed before other integrations ([#3535](https://github.com/getsentry/sentry-react-native/pull/3535)) + - This ensure their frames are correctly symbolicated ### Dependencies diff --git a/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java b/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java index c33750512f..2c0372690b 100644 --- a/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +++ b/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java @@ -705,8 +705,8 @@ public void fetchNativeSdkInfo(Promise promise) { } } - public void fetchNativePackageName(Promise promise) { - promise.resolve(packageInfo.packageName); + public String fetchNativePackageName() { + return packageInfo.packageName; } private void setEventOriginTag(SentryEvent event) { diff --git a/android/src/newarch/java/io/sentry/react/RNSentryModule.java b/android/src/newarch/java/io/sentry/react/RNSentryModule.java index 9f82f68944..c67cc3ddd1 100644 --- a/android/src/newarch/java/io/sentry/react/RNSentryModule.java +++ b/android/src/newarch/java/io/sentry/react/RNSentryModule.java @@ -135,12 +135,13 @@ public WritableMap stopProfiling() { } @Override - public void fetchNativePackageName(Promise promise) { - this.impl.fetchNativePackageName(promise); + public String fetchNativePackageName() { + return this.impl.fetchNativePackageName(); } @Override - public void fetchNativeStackFramesBy(ReadableArray instructionsAddr, Promise promise) { + public WritableMap fetchNativeStackFramesBy(ReadableArray instructionsAddr) { // Not used on Android + return null; } } diff --git a/android/src/oldarch/java/io/sentry/react/RNSentryModule.java b/android/src/oldarch/java/io/sentry/react/RNSentryModule.java index 2d39e8e050..ef478c7d5a 100644 --- a/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +++ b/android/src/oldarch/java/io/sentry/react/RNSentryModule.java @@ -133,13 +133,14 @@ public WritableMap stopProfiling() { return this.impl.stopProfiling(); } - @ReactMethod - public void fetchNativePackageName(Promise promise) { - this.impl.fetchNativePackageName(promise); + @ReactMethod(isBlockingSynchronousMethod = true) + public String fetchNativePackageName() { + return this.impl.fetchNativePackageName(); } - @ReactMethod - public void fetchNativeStackFramesBy(ReadableArray instructionsAddr, Promise promise) { + @ReactMethod(isBlockingSynchronousMethod = true) + public WritableMap fetchNativeStackFramesBy(ReadableArray instructionsAddr) { // Not used on Android + return null; } } diff --git a/ios/RNSentry.mm b/ios/RNSentry.mm index f205b01bfe..90ebeb93b8 100644 --- a/ios/RNSentry.mm +++ b/ios/RNSentry.mm @@ -201,11 +201,10 @@ - (void)setEventEnvironmentTag:(SentryEvent *)event resolve(modulesString); } -RCT_EXPORT_METHOD(fetchNativePackageName:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, fetchNativePackageName) { NSString *packageName = [[NSBundle mainBundle] executablePath]; - resolve(packageName); + return packageName; } - (NSDictionary*) fetchNativeStackFramesBy: (NSArray*)instructionsAddr @@ -273,12 +272,10 @@ - (NSDictionary*) fetchNativeStackFramesBy: (NSArray*)instructionsAdd } } -RCT_EXPORT_METHOD(fetchNativeStackFramesBy:(NSArray *)instructionsAddr - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject) +RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSDictionary *, fetchNativeStackFramesBy:(NSArray *)instructionsAddr) { - resolve([self fetchNativeStackFramesBy:instructionsAddr - symbolicate:dladdr]); + return [self fetchNativeStackFramesBy:instructionsAddr + symbolicate:dladdr]; } RCT_EXPORT_METHOD(fetchNativeDeviceContexts:(RCTPromiseResolveBlock)resolve diff --git a/jest.config.js b/jest.config.js index d8df7d57a8..902b0a443b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ module.exports = { collectCoverage: true, preset: 'react-native', - setupFilesAfterEnv: ['/test/mockConsole.ts'], + setupFilesAfterEnv: ['jest-extended/all', '/test/mockConsole.ts'], globals: { __DEV__: true, 'ts-jest': { diff --git a/package.json b/package.json index 8b2bad470a..2ca7cfcc5a 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "expo-module-scripts": "^3.1.0", "jest": "^29.6.2", "jest-environment-jsdom": "^29.6.2", + "jest-extended": "^4.0.2", "madge": "^6.1.0", "metro": "0.76", "prettier": "^2.0.5", diff --git a/src/js/NativeRNSentry.ts b/src/js/NativeRNSentry.ts index 96aea26e3e..a9d86bdad7 100644 --- a/src/js/NativeRNSentry.ts +++ b/src/js/NativeRNSentry.ts @@ -34,8 +34,8 @@ export interface Spec extends TurboModule { fetchViewHierarchy(): Promise; startProfiling(): { started?: boolean; error?: string }; stopProfiling(): { profile?: string; nativeProfile?: UnsafeObject; error?: string }; - fetchNativePackageName(): Promise; - fetchNativeStackFramesBy(instructionsAddr: number[]): Promise; + fetchNativePackageName(): string | undefined | null; + fetchNativeStackFramesBy(instructionsAddr: number[]): NativeStackFrames | undefined | null; } export type NativeStackFrame = { diff --git a/src/js/integrations/nativelinkederrors.ts b/src/js/integrations/nativelinkederrors.ts index 6c0d8d3945..8f4f5e0566 100644 --- a/src/js/integrations/nativelinkederrors.ts +++ b/src/js/integrations/nativelinkederrors.ts @@ -1,5 +1,6 @@ import { exceptionFromError } from '@sentry/browser'; import type { + Client, DebugImage, Event, EventHint, @@ -53,35 +54,29 @@ export class NativeLinkedErrors implements Integration { /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - const client = getCurrentHub().getClient(); - if (!client) { - return; + public setupOnce(_addGlobalEventProcessor: (callback: EventProcessor) => void, _getCurrentHub: () => Hub): void { + /* noop */ + } + + /** + * @inheritDoc + */ + public preprocessEvent(event: Event, hint: EventHint | undefined, client: Client): void { + if (this._nativePackage === null) { + this._nativePackage = this._fetchNativePackage(); } - addGlobalEventProcessor(async (event: Event, hint?: EventHint) => { - if (this._nativePackage === null) { - this._nativePackage = await this._fetchNativePackage(); - } - const self = getCurrentHub().getIntegration(NativeLinkedErrors); - return self ? this._handler(client.getOptions().stackParser, self._key, self._limit, event, hint) : event; - }); + this._handler(client.getOptions().stackParser, this._key, this._limit, event, hint); } /** * Enriches passed event with linked exceptions and native debug meta images. */ - private async _handler( - parser: StackParser, - key: string, - limit: number, - event: Event, - hint?: EventHint, - ): Promise { + private _handler(parser: StackParser, key: string, limit: number, event: Event, hint?: EventHint): void { if (!event.exception || !event.exception.values || !hint || !isInstanceOf(hint.originalException, Error)) { - return event; + return; } - const { exceptions: linkedErrors, debugImages } = await this._walkErrorTree( + const { exceptions: linkedErrors, debugImages } = this._walkErrorTree( parser, limit, hint.originalException as ExtendedError, @@ -92,25 +87,23 @@ export class NativeLinkedErrors implements Integration { event.debug_meta = event.debug_meta || {}; event.debug_meta.images = event.debug_meta.images || []; event.debug_meta.images.push(...(debugImages || [])); - - return event; } /** * Walks linked errors and created Sentry exceptions chain. * Collects debug images from native errors stack frames. */ - private async _walkErrorTree( + private _walkErrorTree( parser: StackParser, limit: number, error: ExtendedError, key: string, exceptions: Exception[] = [], debugImages: DebugImage[] = [], - ): Promise<{ + ): { exceptions: Exception[]; debugImages?: DebugImage[]; - }> { + } { const linkedError = error[key]; if (!linkedError || exceptions.length + 1 >= limit) { return { @@ -126,7 +119,7 @@ export class NativeLinkedErrors implements Integration { exception = this._exceptionFromJavaStackElements(linkedError); } else if ('stackReturnAddresses' in linkedError) { // isObjCException - const { appleException, appleDebugImages } = await this._exceptionFromAppleStackReturnAddresses(linkedError); + const { appleException, appleDebugImages } = this._exceptionFromAppleStackReturnAddresses(linkedError); exception = appleException; exceptionDebugImages = appleDebugImages; } else if (isInstanceOf(linkedError, Error)) { @@ -193,15 +186,15 @@ export class NativeLinkedErrors implements Integration { /** * Converts StackAddresses to a SentryException with DebugMetaImages */ - private async _exceptionFromAppleStackReturnAddresses(objCException: { + private _exceptionFromAppleStackReturnAddresses(objCException: { name: string; message: string; stackReturnAddresses: number[]; - }): Promise<{ + }): { appleException: Exception; appleDebugImages: DebugImage[]; - }> { - const nativeStackFrames = await this._fetchNativeStackFrames(objCException.stackReturnAddresses); + } { + const nativeStackFrames = this._fetchNativeStackFrames(objCException.stackReturnAddresses); return { appleException: { @@ -218,14 +211,14 @@ export class NativeLinkedErrors implements Integration { /** * Fetches the native package/image name from the native layer */ - private _fetchNativePackage(): Promise { + private _fetchNativePackage(): string | null { return NATIVE.fetchNativePackageName(); } /** * Fetches native debug image information on iOS */ - private _fetchNativeStackFrames(instructionsAddr: number[]): Promise { + private _fetchNativeStackFrames(instructionsAddr: number[]): NativeStackFrames | null { return NATIVE.fetchNativeStackFramesBy(instructionsAddr); } } diff --git a/src/js/wrapper.ts b/src/js/wrapper.ts index b108a84eb2..7a315c9161 100644 --- a/src/js/wrapper.ts +++ b/src/js/wrapper.ts @@ -85,12 +85,12 @@ interface SentryNativeWrapper { startProfiling(): boolean; stopProfiling(): { hermesProfile: Hermes.Profile; nativeProfile?: NativeProfileEvent } | null; - fetchNativePackageName(): Promise; + fetchNativePackageName(): string | null; /** * Fetches native stack frames and debug images for the instructions addresses. */ - fetchNativeStackFramesBy(instructionsAddr: number[]): Promise; + fetchNativeStackFramesBy(instructionsAddr: number[]): NativeStackFrames | null; } const EOL = utf8ToBytes('\n'); @@ -554,7 +554,7 @@ export const NATIVE: SentryNativeWrapper = { } }, - async fetchNativePackageName(): Promise { + fetchNativePackageName(): string | null { if (!this.enableNative) { return null; } @@ -562,10 +562,10 @@ export const NATIVE: SentryNativeWrapper = { return null; } - return (await RNSentry.fetchNativePackageName()) || null; + return RNSentry.fetchNativePackageName() || null; }, - async fetchNativeStackFramesBy(instructionsAddr: number[]): Promise { + fetchNativeStackFramesBy(instructionsAddr: number[]): NativeStackFrames | null { if (!this.enableNative) { return null; } @@ -573,7 +573,7 @@ export const NATIVE: SentryNativeWrapper = { return null; } - return (await RNSentry.fetchNativeStackFramesBy(instructionsAddr)) || null; + return RNSentry.fetchNativeStackFramesBy(instructionsAddr) || null; }, /** diff --git a/test/integrations/integrationsexecutionorder.test.ts b/test/integrations/integrationsexecutionorder.test.ts new file mode 100644 index 0000000000..7a9e9f5def --- /dev/null +++ b/test/integrations/integrationsexecutionorder.test.ts @@ -0,0 +1,98 @@ +import * as mockWrapper from '../mockWrapper'; +jest.mock('../../src/js/wrapper', () => mockWrapper); +jest.mock('../../src/js/utils/environment'); + +import { defaultStackParser } from '@sentry/browser'; +import type { Integration } from '@sentry/types'; + +import { ReactNativeClient } from '../../src/js/client'; +import { getDefaultIntegrations } from '../../src/js/integrations/default'; +import type { ReactNativeClientOptions } from '../../src/js/options'; +import { isHermesEnabled, notWeb } from '../../src/js/utils/environment'; +import { MOCK_DSN } from '../mockDsn'; + +describe('Integration execution order', () => { + describe('mobile hermes', () => { + beforeEach(() => { + (notWeb as jest.Mock).mockReturnValue(true); + (isHermesEnabled as jest.Mock).mockReturnValue(true); + }); + + it('NativeLinkedErrors is before RewriteFrames', async () => { + // NativeLinkedErrors has to process event before RewriteFrames + // otherwise the linked errors stack trace frames won't be rewritten + + const client = createTestClient(); + const { integrations } = client.getOptions(); + + const nativeLinkedErrors = spyOnIntegrationById('NativeLinkedErrors', integrations); + const rewriteFrames = spyOnIntegrationById('RewriteFrames', integrations); + + client.setupIntegrations(); + + client.captureException(new Error('test')); + jest.runAllTimers(); + + expect(nativeLinkedErrors.preprocessEvent).toHaveBeenCalledBefore(rewriteFrames.processEvent!); + }); + }); + + describe('web', () => { + beforeEach(() => { + (notWeb as jest.Mock).mockReturnValue(false); + (isHermesEnabled as jest.Mock).mockReturnValue(false); + }); + + it('LinkedErrors is before RewriteFrames', async () => { + // LinkedErrors has to process event before RewriteFrames + // otherwise the linked errors stack trace frames won't be rewritten + + const client = createTestClient(); + const { integrations } = client.getOptions(); + + const linkedErrors = spyOnIntegrationById('LinkedErrors', integrations); + const rewriteFrames = spyOnIntegrationById('RewriteFrames', integrations); + + client.setupIntegrations(); + + client.captureException(new Error('test')); + jest.runAllTimers(); + + expect(linkedErrors.preprocessEvent).toHaveBeenCalledBefore(rewriteFrames.processEvent!); + }); + }); +}); + +interface IntegrationSpy { + name: string; + setupOnce?: Integration['setupOnce'] & jest.Mock; + preprocessEvent?: Integration['preprocessEvent'] & jest.Mock; + processEvent?: Integration['processEvent'] & jest.Mock; +} + +function spyOnIntegrationById(id: string, integrations: Integration[]): IntegrationSpy { + const candidate = integrations?.find(integration => integration.name === id); + if (!candidate) { + throw new Error(`Integration ${id} not found`); + } + + jest.spyOn(candidate, 'setupOnce'); + candidate.preprocessEvent && jest.spyOn(candidate, 'preprocessEvent'); + candidate.processEvent && jest.spyOn(candidate, 'processEvent'); + return candidate as IntegrationSpy; +} + +function createTestClient(): ReactNativeClient { + const clientOptions: ReactNativeClientOptions = { + dsn: MOCK_DSN, + transport: () => ({ + send: jest.fn().mockResolvedValue(undefined), + flush: jest.fn().mockResolvedValue(true), + }), + stackParser: defaultStackParser, + integrations: [], + }; + clientOptions.integrations = getDefaultIntegrations(clientOptions); + + return new ReactNativeClient(clientOptions); +} diff --git a/test/integrations/nativelinkederrors.test.ts b/test/integrations/nativelinkederrors.test.ts index b27258fe38..9303255d43 100644 --- a/test/integrations/nativelinkederrors.test.ts +++ b/test/integrations/nativelinkederrors.test.ts @@ -1,5 +1,5 @@ import { defaultStackParser } from '@sentry/browser'; -import type { DebugImage, Event, EventHint, ExtendedError, Hub } from '@sentry/types'; +import type { Client, DebugImage, Event, EventHint, ExtendedError } from '@sentry/types'; import { NativeLinkedErrors } from '../../src/js/integrations/nativelinkederrors'; import type { NativeStackFrames } from '../../src/js/NativeRNSentry'; @@ -7,9 +7,9 @@ import { NATIVE } from '../../src/js/wrapper'; jest.mock('../../src/js/wrapper'); -(NATIVE.fetchNativePackageName as jest.Mock).mockImplementation(() => Promise.resolve('mock.native.bundle.id')); +(NATIVE.fetchNativePackageName as jest.Mock).mockImplementation(() => 'mock.native.bundle.id'); -(NATIVE.fetchNativeStackFramesBy as jest.Mock).mockImplementation(() => Promise.resolve(null)); +(NATIVE.fetchNativeStackFramesBy as jest.Mock).mockImplementation(() => null); describe('NativeLinkedErrors', () => { beforeEach(() => { @@ -181,43 +181,44 @@ describe('NativeLinkedErrors', () => { }); it('adds ios objective-c cause from the original error to the event', async () => { - (NATIVE.fetchNativeStackFramesBy as jest.Mock).mockImplementation(() => - Promise.resolve({ - frames: [ - // Locally symbolicated frame - { - platform: 'cocoa', - package: 'CoreFoundation', - function: '__exceptionPreprocess', - symbol_addr: '0x0000000180437330', - instruction_addr: '0x0000000180437330', - image_addr: '0x7fffe668e000', - }, - { - platform: 'cocoa', - function: 'objc_exception_throw', - instruction_addr: '0x0000000180051274', - image_addr: '0x7fffe668e000', - }, - { - platform: 'cocoa', - package: 'mock.native.bundle.id', - instruction_addr: '0x0000000103535900', - image_addr: '0x7fffe668e000', - in_app: true, - }, - ], - debugMetaImages: [ - { - type: 'macho', - debug_id: '84a04d24-0e60-3810-a8c0-90a65e2df61a', - code_file: '/usr/lib/libDiagnosticMessagesClient.dylib', - image_addr: '0x7fffe668e000', - image_size: 8192, - image_vmaddr: '0x40000', - }, - ], - }), + (NATIVE.fetchNativeStackFramesBy as jest.Mock).mockImplementation( + () => + { + frames: [ + // Locally symbolicated frame + { + platform: 'cocoa', + package: 'CoreFoundation', + function: '__exceptionPreprocess', + symbol_addr: '0x0000000180437330', + instruction_addr: '0x0000000180437330', + image_addr: '0x7fffe668e000', + }, + { + platform: 'cocoa', + function: 'objc_exception_throw', + instruction_addr: '0x0000000180051274', + image_addr: '0x7fffe668e000', + }, + { + platform: 'cocoa', + package: 'mock.native.bundle.id', + instruction_addr: '0x0000000103535900', + image_addr: '0x7fffe668e000', + in_app: true, + }, + ], + debugMetaImages: [ + { + type: 'macho', + debug_id: '84a04d24-0e60-3810-a8c0-90a65e2df61a', + code_file: '/usr/lib/libDiagnosticMessagesClient.dylib', + image_addr: '0x7fffe668e000', + image_size: 8192, + image_vmaddr: '0x40000', + }, + ], + }, ); const actualEvent = await executeIntegrationFor( @@ -338,29 +339,16 @@ describe('NativeLinkedErrors', () => { }); }); -function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint): Promise { +function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint): Event | null { + const mockedClient = { + getOptions: () => ({ + stackParser: defaultStackParser, + }), + } as unknown as Client; + const integration = new NativeLinkedErrors(); - return new Promise((resolve, reject) => { - integration.setupOnce( - async eventProcessor => { - try { - const processedEvent = await eventProcessor(mockedEvent, mockedHint); - resolve(processedEvent); - } catch (e) { - reject(e); - } - }, - () => - ({ - getClient: () => ({ - getOptions: () => ({ - stackParser: defaultStackParser, - }), - }), - getIntegration: () => integration, - } as unknown as Hub), - ); - }); + integration.preprocessEvent(mockedEvent, mockedHint, mockedClient); + return mockedEvent; } function createNewError(from: { message: string; name?: string; stack?: string; cause?: unknown }): ExtendedError { diff --git a/typings/jest-extended.d.ts b/typings/jest-extended.d.ts new file mode 100644 index 0000000000..9e6c1dbd9f --- /dev/null +++ b/typings/jest-extended.d.ts @@ -0,0 +1 @@ +import 'jest-extended'; diff --git a/yarn.lock b/yarn.lock index e37d37f4b6..be98b2ac93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6374,6 +6374,11 @@ diff-sequences@^29.4.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -8889,6 +8894,16 @@ jest-config@^29.6.2: slash "^3.0.0" strip-json-comments "^3.1.1" +jest-diff@^29.0.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + jest-diff@^29.3.1: version "29.3.1" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527" @@ -8997,6 +9012,19 @@ jest-expo@~50.0.0-alpha.0: react-test-renderer "18.2.0" stacktrace-js "^2.0.2" +jest-extended@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/jest-extended/-/jest-extended-4.0.2.tgz#d23b52e687cedf66694e6b2d77f65e211e99e021" + integrity sha512-FH7aaPgtGYHc9mRjriS0ZEHYM5/W69tLrFTIdzm+yJgeoCmmrSB/luSfMSqWP9O29QWHPEmJ4qmU6EwsZideog== + dependencies: + jest-diff "^29.0.0" + jest-get-type "^29.0.0" + +jest-get-type@^29.0.0, jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + jest-get-type@^29.2.0: version "29.2.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" @@ -9007,11 +9035,6 @@ jest-get-type@^29.4.3: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - jest-haste-map@^29.6.2: version "29.6.2" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.2.tgz#298c25ea5255cfad8b723179d4295cf3a50a70d1"