21

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

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Or Assayag
  • 5,662
  • 13
  • 57
  • 93
  • 1
    What version of Firefox are you testing on? This [is supported with no pref flipping since version 79](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer). See the compatibility table on that page. – Dexter Nov 03 '20 at 11:02
  • 1
    I'm using Firefox 82.0.2 (64-bit), and get this exception. – Or Assayag Nov 03 '20 at 13:11
  • 1
    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](https://hacks.mozilla.org/2020/07/safely-reviving-shared-memory/) blog post for why this was needed to mitigate the Spectre security flaw. – Dexter Nov 03 '20 at 15:43
  • 1
    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`). – Ed Graham Jan 02 '21 at 18:29
  • 3
    jsdom triggered the error for me. – jake Mar 11 '21 at 00:59

4 Answers4

16

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

MayeulC
  • 1,628
  • 17
  • 24
stephane k.
  • 1,668
  • 20
  • 21
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:

agektmr
  • 2,144
  • 15
  • 14
4

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();
    });
};
dekajoo
  • 2,024
  • 1
  • 25
  • 36
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>
  • 5
    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. – Brandon Dec 02 '21 at 03:08