React Error: "SharedArrayBuffer is not defined" in Firefox
W

5

25

I have a React app, created with 'create-react-app' (I also use jsdom NPM package), and for some reason, the application throws an error on load Only in Firefox (works fine in Chrome & Edge).
Here is the error:

ReferenceError: SharedArrayBuffer is not defined
./node_modules/jsdom/node_modules/webidl-conversions/lib/index.js
C:/Or/Web/WorldCovid/WorldCovid/node_modules/jsdom/node_modules/webidl-conversions/lib/index.js:347

  344 | 
  345 | const abByteLengthGetter =
  346 |     Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get;
> 347 | const sabByteLengthGetter =
  348 |     Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, "byteLength").get;
  349 | 
  350 | function isNonSharedArrayBuffer(V) {

After some Googling I found:
"To enable SharedArrayBuffer in Firefox, go to about:config and set the javascript.options.shared_memory preference to true" (https://github.com/ggerganov/kbd-audio/issues/9)
The problem is that it was already enabled to true.

Did anyone face this issue before? Thanks.

UPDATE:

Tried to convert to:

const shared = new SharedArrayBuffer(1024);

const abByteLengthGetter =
    Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get;
const sabByteLengthGetter =
    Object.getOwnPropertyDescriptor(shared.prototype, "byteLength").get;

Still get the same error (different line to the SharedArrayBuffer object).

Wheel answered 2/11, 2020 at 17:11 Comment(5)
What version of Firefox are you testing on? This is supported with no pref flipping since version 79. See the compatibility table on that page.Witherite
I'm using Firefox 82.0.2 (64-bit), and get this exception.Wheel
Have you checked the "Security requirements" section of the MDN page? You may need some Cross-Origin magic (for security reasons). See the Mozilla Hacks blog post for why this was needed to mitigate the Spectre security flaw.Witherite
I get this, too - exactly the error the @OrAssayag describes, and also only in Firefox. I also used create-react-app and the jsdom npm package (along with axios).Bornite
jsdom triggered the error for me.Aubreir
B
23

You need to set two response headers for your document:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

These are new security requirements for using SharedArrayBuffer.

You can check in code if cross origin isolation is enabled:

if (crossOriginIsolated) {
    // SharedArrayBuffer is available
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer

Bureaucratize answered 11/1, 2021 at 22:24 Comment(4)
how do you do this is react when youre not compiling a static build or using server-side rendering?Clasping
Please tell me how to do it in reactjs projectLibra
The linked MDN doc says COEP can be 'credentialless' as well; this works on Chrome but Firefox wouldn't isolate until I set it to 'require-corp'Acarpous
@Clasping Heres how you can do it in development mode. Once you deploy configure your server (Apache, Gitlab Pages, etc.) accordingly.Ruder
G
9

The React issue has been fixed and released in 17.0.2. They say there's no plan to backport the change to older versions, but this shouldn't be a big issue unless you are expecting high-precision performance measurement on React.

SharedArrayBuffer has been disabled across all browsers except Chrome desktop since the discovery of Spectre, but Chrome desktop also disables it starting in Chrome 92. You'll need "cross-origin isolation" to enable it.

When you encounter an issue: Uncaught ReferenceError: SharedArrayBuffer is not defined on Chrome, you'll need to apply "cross-origin isolation" to continue using SharedArrayBuffer, but as an escape-hatch, you can request an origin trial to allowlist your site to continue using SharedArrayBuffer without cross-origin isolation at least until Chrome 96.

To enable cross-origin isolation, you must send two HTTP headers (COOP and COEP) as @stephane k. mentioned in the other comment.

To learn more about cross-origin isolation, read:

Gynecium answered 9/6, 2021 at 8:20 Comment(0)
F
5

As said before, due to Spectre vulnerability, SharedArrayBuffer have been disabled on most browsers unless you specify Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers.

If you want to activate such headers on react dev server locally you can configure the proxy manually that adds headers using a custom middleware.

Created a src/setupProxy.js file with:

module.exports = function (app) {
    app.use(function (req, res, next) {
        res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
        res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
        next();
    });
};
Frum answered 17/8, 2022 at 8:27 Comment(0)
K
3

In index.html file, you add script like below. I think it will be helpful. And I did.

<body>
<script>
  if (!crossOriginIsolated) SharedArrayBuffer = ArrayBuffer;
</script>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="app"></div>
Kutch answered 19/8, 2021 at 9:36 Comment(1)
This will prevent the SharedArrayBuffer from actually being shareable between workers and the main thread, which will most likely break the code that is depending on the SharedArrayBuffer. This solution is a good quick fix if you can tolerate workers not actually doing their job and you are just trying to silence an error that doesn't have any real impact on the application, but if you don't really know what you're doing, you may just be masking a problem that may cause issues down the road. If you control the worker code it's probably better to just not run the worker in the first place.Natation
I
2

Add below package details - https://github.com/gzuidhof/coi-serviceworker

  1. Download coi-serviceworker.js (or coi-serviceworker.min.js).
  2. Put it next to your index file (or in any folder above it)
  3. Add to your HTML file: <script src="coi-serviceworker.js"></script>

This script will reload the page on the user's first load to magically add the required COOP and COEP headers in a service worker.

Rules:

  1. It must be in a separate file, you can't bundle it along with your app.
  2. It can't be loaded from a CDN: it must be served from your own origin.
  3. Your page will still need to be either served from HTTPS, or served from localhost.

For more details, see this

Note: This is quick fix.

Infectious answered 30/1 at 17:38 Comment(1)
This will work if you are deploying the site as static build, e.g. gh-pages. I was using vite + react and statuc build deploy to gh-pages and this lib worked.Deviate

© 2022 - 2024 — McMap. All rights reserved.