react-native: Cannot assign to read only property 'performance' of object '[object global]'

Description

FAIL src/Containers/Contacts/tests/Contacts.test.js ● Test suite failed to run

TypeError: Cannot assign to read only property 'performance' of object '[object global]'

  at Object.<anonymous> (node_modules/react-native/jest/setup.js:405:20)

image

Version

0.68.5

Output of npx react-native info

System: OS: macOS 13.0.1 CPU: (8) arm64 Apple M1 Memory: 781.28 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 19.3.0 - /opt/homebrew/bin/node Yarn: 1.22.19 - /opt/homebrew/bin/yarn npm: 9.2.0 - /opt/homebrew/bin/npm Watchman: 2022.12.12.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.3 - /Users/user/.rbenv/shims/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: Not Found IDEs: Android Studio: 2021.3 AI-213.7172.25.2113.9014738 Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: 11.0.16.1 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 17.0.2 => 17.0.2 react-native: 0.68.5 => 0.68.5 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

Run nvm use yarn test.

It works for node 18.12.1, but not for node 19.3.0.

Snack, code example, screenshot, or link to a repository

Works on lts/hydrogen -> v18.12.1. But because node 19 decides to make global performance property as read only ({writable: false})

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 16
  • Comments: 16

Commits related to this issue

Most upvoted comments

The problem is in node version indeed. I was using stable node version on my project and I had node installed with homebrew (that is system node version). NVM prioritizes system-node over default alias, so jest was using node v19 that triggers this error. I had to remove system node version. Now jest is running on stable node version

FIX: brew uninstall node nvm use stable

solved in jest 29.6.4 version

For me this is still not being solved, using jest 29.7.0

I got this error after upgrading to node v19. Changing these lines https://github.com/facebook/react-native/blob/473eb1dd870a4f62c4ebcba27e12bde1e99e3d07/jest/setup.js#L20-L22 to something like

if (!global.performance) {
  global.performance = {}
}
global.performance.now = jest.fn(Date.now)

Might solve the issue. I’m guessing that node v18/19 started defining performance or added a guard that prevents reassigning it. Couldn’t find anything related in the release notes though.

Hello.

I encountered this error when running Jest in a Node.js project (not a React Native project).

If the issue is that the global object’s performance is read-only, it seems like the following explicit declaration could resolve it (at least it worked for me). However, is there anything problematic with this?

Object.defineProperty(global, "performance", {
  writable: true,
});

(Admittedly, modifying the global object easily may not be a good practice.)

Worth linking this here: https://github.com/nodejs/node/issues/51048 (this same issue being reported directly to Node).

I’ve run into this on a project using Jest and this is the only issue I could find with the exact error I was seeing - it broke between node 18.18 and 18.19 - Jest relies on descriptor.writable but it’s not longer returned in the descriptor:

$ docker run --rm -it node:18.18 node 
Welcome to Node.js v18.18.2.
Type ".help" for more information.
> Object.getOwnPropertyDescriptor(globalThis, 'performance');
{
  value: Performance {
    nodeTiming: PerformanceNodeTiming {
      name: 'node',
      entryType: 'node',
      startTime: 0,
      duration: 1273.0532480003312,
      nodeStart: 1.4266739999875426,
      v8Start: 6.116002000402659,
      bootstrapComplete: 25.822167000267655,
      environment: 13.395024999976158,
      loopStart: 42.115690000355244,
      loopExit: -1,
      idleTime: 1205.711491
    },
    timeOrigin: 1701690439884.343
  },
  writable: true,
  enumerable: true,
  configurable: true
}
$ docker run --rm -it node:18.19 node
Welcome to Node.js v18.19.0.
Type ".help" for more information.
> Object.getOwnPropertyDescriptor(globalThis, 'performance');
{
  get: [Function: get performance],
  set: [Function: set performance],
  enumerable: true,
  configurable: true
}

Hello. I encountered this error when running Jest in a Node.js project (not a React Native project). If the issue is that the global object’s performance is read-only, it seems like the following explicit declaration could resolve it (at least it worked for me). However, is there anything problematic with this?

Object.defineProperty(global, "performance", {
  writable: true,
});

(Admittedly, modifying the global object easily may not be a good practice.)

@manattan where did you put it?

I ended up with this patch in react-native/jest/setup.js:

Replaced this code

...
global.performance = {
    now: jest.fn(Date.now),
};

with this code

...
Object.defineProperty(global, "performance", {
  writable: true,
});
...

Node: 21.5.0 Jest: 29.7.0 React Native: 0.71.13

UPDATE:

My initial patch caused a different error on some machines

TypeError: Cannot read properties of undefined (reading 'now')

So I (with the help of ChatGPT) refactored the code to

const performanceDescriptor = Object.getOwnPropertyDescriptor(global, 'performance');
if (!performanceDescriptor || performanceDescriptor.configurable) {
  Object.defineProperty(global, 'performance', {
    value: {
      now: jest.fn(Date.now),
    },
    writable: true,
  });
} else {
  global.performance.now = jest.fn(Date.now);
}

which seems to be working fine on all machines with this setup: Node: 21.5.0 Jest: 29.7.0 React Native: 0.71.13

solved in jest 29.6.4 version