facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.79k stars 24.29k forks source link

Cannot assign to read only property 'performance' of object '[object global]' #35701

Open Romick2005 opened 1 year ago

Romick2005 commented 1 year ago

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})

mogelbrod commented 1 year ago

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.

Anton-Petrovskyi commented 1 year ago

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

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

mogelbrod commented 1 year ago

Still relevant

github-actions[bot] commented 1 year ago
:warning: Missing Reproducible Example
:information_source: We could not detect a reproducible example in your issue report. Please provide either:
  • If your bug is UI related: a Snack
  • If your bug is build/update related: use our Reproducer Template. A reproducer needs to be in a GitHub repository under your username.
rudda-involves commented 1 year ago

is there a way to override it outside node_modules/react-native/jest/setup.js file?

rudda commented 1 year ago

solved in jest 29.6.4 version

reporter123 commented 1 year ago

looks like jest 29.2.1 is minimum for this fix https://github.com/jestjs/jest/blob/main/CHANGELOG.md

29.6.4 contains additional fixes for node 20.

mrliptontea commented 10 months ago

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
}
toteto commented 10 months ago

solved in jest 29.6.4 version

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

leograde commented 10 months ago

Also not solved for me on 29.7.0 and node v20.3.0

manattan commented 10 months ago

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.)

juanito-caylent commented 10 months ago

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

carlmlane commented 10 months ago

pinning to node version 18.18 was the only way for me to workaround this issue

mrvincenzo commented 9 months ago

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?

mrvincenzo commented 9 months ago

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

github-actions[bot] commented 3 months ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

soryy708 commented 3 months ago

What helped me is upgrading from Jest 28 to Jest 29