endojs / endo

Endo is a distributed secure JavaScript sandbox, based on SES
Apache License 2.0
825 stars 71 forks source link

"TypeError#1" When using Endo with React & Styled Components #1208

Open ramidecodes opened 2 years ago

ramidecodes commented 2 years ago

@endo/init seems to be working well with React v18. But the moment you introduce a component based on StyledComponent library the React App crashes with TypeError#1. There is not much details on the error to continue with the debugging. I'm assuming that StyledComponents is trying to modify some primordial.

Here is a repo to reproduce the issue. https://github.com/ecovirtual/endo-react-styled-components

Could you help me to clarify the console error and see where the issue is coming from?

ramidecodes commented 2 years ago

FYI we found that Emotion, a library with a very similar API as Styled Components works correctly with @Endo/init. For anyone finding this issue and needing to use the styled pattern, you can just keep your styled components and swap your dependency to Emotion. (With little extra migration work)

Here a branch of the initial repo now working with Emotion: https://github.com/ecovirtual/endo-react-styled-components/tree/emotion-styled

livthomas commented 2 years ago

We've run into the same issue. Is @endo/init even supposed to be used in browser environment? If it causes issues for such a simple library like styled-components, I cannot image using it to build a larger application with a ton of dependencies that do crazy stuff in the background.

Do we need to move the code that requires endo to a web worker or something like that?

livthomas commented 2 years ago

After reading Agoric docs, I discovered that @endo/init is probably not the best way how to initialize this environment in a browser. Instead, you need to initiate it manually in a script (e.g. installSesLockdown):

/* global lockdown */
import 'ses'; // adds lockdown, harden, and Compartment
import '@endo/eventual-send/shim.js'; // adds support needed by E

const consoleTaming = import.meta.env.PROD ? 'safe' : 'unsafe';

lockdown({
  __allowUnsafeMonkeyPatching__: 'unsafe',
  errorTaming: 'unsafe',
  overrideTaming: 'severe',
  consoleTaming,
});

Error.stackTraceLimit = Infinity;

And then import it as the very first thing in your React app (e.g. main.jsx):

import './installSesLockdown';

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
...

If you use Webpack instead of Vite (esbuild), you need to replace import.meta.env.PROD with process.env.NODE_ENV === 'production' or something similar.