Hermes: Question: What is similar concept with JSContext in Hermes

Created on 20 Nov 2020  Â·  6Comments  Â·  Source: facebook/hermes

Problem

Hi Hermes team, thank you for a very fast JSEngine to load React Native code.
In our user cases, we have a hosted app, this hosted app is written in native (Objective C/Java), and have some features already written in React Native. The navigation between the Native part and the RN part is very complex.

Let ' say, we have these screens:

  • On the home tab is 4 tab: Home, Profile, and Catalogs is written in native. Feeds is written in RN
  • Product Detail tab is written in Native
  • Seller tab is written in RN

Any Native screens could go to any RN screens and vise versa.
E.g:
Home (Native) -> Product Detail (Native) -> Feeds (RN) -> Seller (RN) -> Product Detail (Native) -> Seller (RN)
Each RN screens have a lot of features inside (e.g: Seller tab shows all products of sellers, their categories, their videos, their feeds, ...). So it is fair to call they are RN app instead of RN screens.

We create a solution to allow all RN apps to share a common code base, we call it dll bundle.
The bundle of an RN app only contains JS code for its logic and libraries which do not have in dll bundle.

What we want is to make sure that each RN app runs into an isolated sandbox environment or JSContext.
With Javascript Core engine, for each RN app, we ran it into a new JSContext which shares the same JSVirtualMachine with JSContext of the dll, then copy the global variables from JSContext of dll.
I describe our approach in more detail in this comment

But with Hermes, I did not know what is a similar concept with JSContext and JSVirtualMachine?

Question

As I understand Hermes Runtime will be similar to JSVirtualMachine, please correct me if I am wrong.
Does Hermes Runtime support multiple Global Execution Context? If not, could we share Objects between 2 Hermes Runtime?

Thanks

Most helpful comment

Your description is similar to realms: each realm has its own separate global object but all realms share a heap, so values can be shared. Unfortunately Hermes does not provide this functionality yet, although we have discussed it internally and it is possible to implement.

All 6 comments

Your description is similar to realms: each realm has its own separate global object but all realms share a heap, so values can be shared. Unfortunately Hermes does not provide this functionality yet, although we have discussed it internally and it is possible to implement.

Hi @tmikov, thank you for replying.
Until realm is implemented in Hermes, is there any way I could workaround?
E.g: could I create a new Hermes Runtime, and clone object from another Runtime to the new one I just create?

I am willing to dig more into Hermes source code to know more detais about how Hermes works. Actually I also take a look at the API packages, but for now, I only underatand a tiny amount of the source code. So if possible, could you please tell me what part in source code I should dig more to implement the isolation feafure.

Thanks

What is in the objects you currently share? How heavyweight are they?

In my usercases, I want to share 2 types of objects between Runtime / Context

• objects point to Native Modules - they are lightweight because I only need to pass C++ pointer
• objects point to an JS module source code, my idea is fhe first runtime parse the common JS library, and then the 2nd runtime could point to the first one, and the 2nd runtime only needs to load its separated logic. By using this approach, I expect could improve the loading time of 2nd Runtime

@mhorowitz is that possible with Hermes current API?

Thanks

objects point to Native Modules

This is easily possible. Two JSI HostObjects can hold the same C++ pointer, or a shared_ptr to your data. Depending on how you use this data, you may need to take care to avoid issues with multithreaded access to data structures. This will be a concern for your C++ code, not for JS or Hermes.

objects point to an JS module source code, my idea is fhe first runtime parse the common JS library, and then the 2nd runtime could point to the first one, and the 2nd runtime only needs to load its separated logic. By using this approach, I expect could improve the loading time of 2nd Runtime

If you compile the JS to Hermes bytecode ahead of time, when building your application, you can load that bytecode efficiently with JSIRuntime::evaluateJavaScript. This is lightweight and usually much faster than loading JS code. If loading the JS module creates any JS objects, those would be independent in each Runtime instance. Note that this would not look like loading the code in runtime A, and then referring to it from runtime B. You would create a single jsi::Buffer C++ object (ideally using FileBuffer in jsilib.h, which uses mmap to reference the bytecode from disk), then pass the buffer individually to a.evaluateJavaScript() and b.evaluateJavaScript(). The contents of a bytecode buffer are read-only to the runtime, so it can be safely shared in this way.

Thanks @mhorowitz.
When thinking more about sharing the same dll between 2 runtime A and B, I also see some issues related to global variables, and internal variables (which related to AppRegistry and Native View registry in React Native). So I also started thinking about how to duplicated load dll between 2 runtimes.
I will try to implement as you suggest and will come back if I got any questions.

Cheers

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NWU-NISL picture NWU-NISL  Â·  4Comments

Kikketer picture Kikketer  Â·  3Comments

benjamingr picture benjamingr  Â·  6Comments

Huxpro picture Huxpro  Â·  4Comments

tsengvn picture tsengvn  Â·  4Comments