react-native-community / discussions-and-proposals

Discussions and proposals related to the main React Native project
https://reactnative.dev
1.66k stars 126 forks source link

JSI (JavaScript Interface) & JSC (JavaScript Core) Discussion #91

Closed kelset closed 2 years ago

kelset commented 5 years ago

What's the current status of JSI? Read here

Intro

With this issue I'd like to try and create a "one stop" for all the information available around the JavaScript Interface, the unified lightweight general purpose API for (theoretically) any JavaScript virtual machine.

Currently, the default Javascript Virtual Machine used by React Native is JavaScriptCore (JSC) - it is used in WebKit.

Terminology

TL;DR

From @axe-fb's blogpost, here's a temporary description of the JSI (please consider that this is not yet finalized, it may change in the future)

Instead of using the bridge for queuing messages, the new architecture allows us to directly "invoke" (think RPC) Java/ObjC methods. An analogy would be how we call DOM methods from JavaScript in the browser. For example, in the statement var el = document.createElement('div'); the variable el holds a reference not to a JavaScript object, but to an object that was possibly instantiated in C++. When JavaScript calls el.setAttribute('width', 100), we end up synchronously invoking the setWidth method in C++ that changes the actual width of that element. In React Native, we can similarly use the JavaScript interface to invoke methods on UI Views and Native Modules that are implemented in Java/ObjC.

Available Materials

At ReactConf 2018 @axe-fb did a talk about React Native's New Architecture, which also explains the 3 concepts above: JSI, Fabric, TurboModule.

Recently the JSC was upgraded for Android, you can check the commit here and the related issue in the main repo.

On twitter, @karanjthakkar did a thread detailing how he integrated the new JSC in the Skyscanner app.

In Q1 2019, @kelset wrote a high level explanation in a blogpost: https://formidable.com/blog/2019/jsi-jsc-part-2/ and did a talk about the whole rearchitecture in April 2019 at React Edinburgh.

Over on twitter, @ericlewis published a sample repo with @chrfalch to showcase how to use directly C++ in a RN app (thanks to the JSI): https://github.com/ericlewis/react-native-hostobject-demo

@kelset also did a more in-depth talk at React Advanced London in Oct 2019: youtube recording & slides.

@Jarred-Sumner published a quick benchmark difference between a lib and a reimplementation using JSI twitter.

Libraries implemented using JSI

Blogposts

Q&A

This is also a place for questions related to this effort and its direction.

Eyesonly88 commented 5 years ago

I have a couple of questions:

Kudo commented 5 years ago

@Eyesonly88

Why doesn't React Native use the same exact JSC for iOS and Android? AFAIK, Android JSC !== iOS JSC (correct me if I'm wrong)

Even at the same version of JSC, the Android implementation is different to iOS. So that Android JSC will always not equal to iOS. Furthermore, different iOS versions have different JSCs.

Is it even possible to use something else other than JSC for iOS? AFAIK, even Chrome doesn't use V8 on iOS: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/zINHc4_dWhk

Yes, JSI brings a benefit for other platforms to use different JavaScript engine easier. E.g. react-native-windows will use CharkaCore

BTW Chrome does not use v8 on iOS simply because they should follows App Store Review Guidelines

2.5.6 Apps that browse the web must use the appropriate WebKit framework and WebKit Javascript.

Eyesonly88 commented 5 years ago

@Kudo interesting, thanks for the reply.

Yeah, regarding V8 on iOS, that's what I was wondering about, even if RN provided a way to use other engines, we're stuck with JSC on iOS due to App Store rules.

Pikaurd commented 5 years ago

@Eyesonly88 Please check @Kudo comment 2.5.6 Apps that browse the web must use the appropriate WebKit framework and WebKit Javascript. That focus "browse the web". Chrome is a web browser therefore google has to obey it.

sJJdGG commented 5 years ago

@Pikaurd @Eyesonly88 Yeah I also think @Kudo is right regarding usage of V8 and theoretically it should already be possible to submit V8-powered RN-based apps to app store review process and getting accepted considering JSI efforts on RN side and more importantly the almost new announced JIT-less V8 on V8 side.

But really eager to see a practical example that's accepted to app store.

To me biggest benefit of V8 (In addition to other common reasons) could be V8 snapshots that should help boosting startup times considering parsing javascript is a significant chunk of overall code execution time.

Eyesonly88 commented 5 years ago

@sJJdGG I'm happy to try it in one of my production apps, any guide on how would I go about doing that? (I'd do anything to improve startup time)

sercand commented 5 years ago

@sJJdGG @Eyesonly88 ReactNative supports another bundle option which is ByteCode Bundle. It is not documented and I guess facebook uses it in their app. It must be be similar to V8 snapshots.

aleclarson commented 5 years ago

Does this have any implications for WebAssembly interop with React Native?

kirillpisarev commented 5 years ago

I still can't figure out how JSI will solve the problem with RN viewport size suspense in case of embedding RN within a native project? As i understand the flow now is like:

  1. init RN native
  2. init RN JS
  3. build JS shadow tree
  4. draw native

During all this time the viewport doesn't know the size of content that leads to UI problems.

So what will be changed to solve exactly this problem?

kelset commented 5 years ago

the viewport doesn't know the size of content that leads to UI problems

my understanding is that actually through JSI & Fabric, the viewport will know. But I may be wrong.

oNaiPs commented 5 years ago

Hi guys, we have been working on a JSI implementation for node. Idea is to be able to re-use JS<->C++ modules that work in both React Native and Node/Electron. We think JSI has a great potential to become an API for cross-runtime implementations.

We also worked on a C++ template system that allows us to define C++ classes that map easier to a JS object, without any codegen tools.

We would like to share our effort with the community, but would like some guidance on how we could do that, perhaps with some mentoring from people that is involved with JSI implementation.

Thanks

akshetpandey commented 5 years ago

So I have some code using turbomodules but I understandably can't run it in remote debug mode since that runs with the remote chrome js engine. What is the workaround and what does the debug DX look like for JSI HostObjects and turbomodules?

terrysahaidak commented 5 years ago

@akshetpandey I as remember, the current workaround is to have both JSI and the bridge and switching between them when you debugging.

When you're using JSI, your module available using global object, but once you've switched to a remote debugger, use NativeModules instead (if you have bindings).

You can check out @chrfalch's reanimated JSI example (might be outdated a bit): https://github.com/kmagiera/react-native-reanimated/compare/master...chrfalch:jsi-methods

elicwhite commented 5 years ago

When using JSI, we currently recommend using safari to debug the JSC instance running on device, or on Android if you are using Hermes, you can connect Chrome to the instance of Hermes running on device.

terrysahaidak commented 4 years ago

Is there any article/example/docs on how to properly use JSI on Android? Maybe there is already module in current master which uses JSI on Android? I would appreciate any link.

kelset commented 4 years ago

@terrysahaidak I think that the closest thing to that atm is: https://github.com/ericlewis/react-native-hostobject-demo/pull/4

terrysahaidak commented 4 years ago

This looks cool and I've already seen it, but not quite sure how to trigger Java code from C++. By the way, does CodeGen is usable in any kind already?

kelset commented 4 years ago

I'm not sure about it being usable - afaik it's still under heavy development. But you can check it out here -> https://github.com/facebook/react-native/tree/master/packages/react-native-codegen

chrfalch commented 4 years ago

@tomduncalf added a pull request to Eric and my repository showing how to add support for JSI on Android, don't know if that can be used?

https://github.com/ericlewis/react-native-hostobject-demo/pull/4

terrysahaidak commented 4 years ago

Here is my attempt to get JSI working on android. And yeah, JSI definitely works, but also JNI works as well! So yeah, we can call Java from JS right now: https://github.com/terrysahaidak/host-object-test/blob/master/libs/android-jsi/test-jsi/src/main/cpp/TestJSIInstaller.cpp

ghost commented 4 years ago

I've been experimenting with JSI and enjoying the results but I can't figure out how one is expected to resolve a promise from a native worker thread. A reference to the runtime is required to invoke resolve or reject but the reference available when the promise is created is not valid for use within the worker thread. Is there an example somewhere of how this should be done?

chrfalch commented 4 years ago

@sdc395biosite You can take a look at some of the conversions between JSI <-> JavaScript in the React Native repo here: ReactCommon/turbomodule/core/TurboModuleUtils.cpp.

ghost commented 4 years ago

@chrfalch Thanks for the rapid response. I've read through the code but I'm not sure what I'm supposed to see. Is JSCallInvoker the key? Does this mean calls to JS from JSI still use the bridge? I was expecting to be able to use something like JNI's AttachCurrentThread or that the runtime would block my thread, queue the call to JS for the next process tick, and then release my thread with the result.

WillerZ commented 4 years ago

Is there any reference documentation for JSI? I have been looking for something comparable to the N-API docs and found nothing with that level of reference material in it.

tomduncalf commented 4 years ago

@WillerZ as I understand it, there are no reference docs yet because JSI is still somewhat in flux. For now you just have to look at header files and example code (e.g. RNTester) I’m afraid

kelset commented 4 years ago

ditto what @tomduncalf is saying, the jsi header file is probably the best documentation atm.

rhdeck commented 4 years ago

Could I get a quick clarification on that? Is JSI substantially in flux, or is is just undocumented? E.g. is there a documentation problem to be solved, or is it so fluid that it's not worth anyone pursuing?

On Mon, Jan 6, 2020 at 5:00 AM Lorenzo Sciandra notifications@github.com wrote:

ditto what @tomduncalf https://github.com/tomduncalf is saying, the jsi header file is probably the best documentation atm.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/react-native-community/discussions-and-proposals/issues/91?email_source=notifications&email_token=AC5C774CWEQM5AVZJNRHHSLQ4MFLJA5CNFSM4GSGGK62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIFD6PY#issuecomment-571096895, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC5C772VRHYQBCOX3KQXV23Q4MFLJANCNFSM4GSGGK6Q .

kelset commented 4 years ago

I think that the last word around this should be given by someone from the FB on this.

But I feel it's quite stable; according to the commit history of the folder it's been lightly touched in the last few months.

That said, I wouldn't consider it "officially stable" until there is documentation on the main website.

chrfalch commented 4 years ago

JSI is a requirement to implement Fabric, which is required to get async rendering with suspense and all those new goodies from React to React Native.

I don't think there are any plans for pushing JSI as the new way of building native modules in the near future - tooling problems like debugging under Chrome not working with JSI modules makes JSI a bit developer unfriendly.

mhorowitz commented 4 years ago

Hi, I'm the main author of JSI, and @TheSavior asked me to comment on this thread.

I would say that JSI is mostly stable. We have no plans to make substantive changes, but we're not ready to declare the API perfectly "stable", either. We have some ideas for improvements, but they are not fully baked, and may require some iteration.

The main improvements we've discussed internally are around making HostFunction a more robust API. For example, the arguments are passed as just a pointer and length which is simple and familiar, but we've seen bugs where people forget to do bounds checks. So we may choose to introduce a object to hold arguments in order to make it possible to do validation.

There has also been interest in making an ABI-stable variant of JSI, which would benefit people shipping binary modules. We're still pinning down what the exact requirements are and how this would affect JSI.

I hope this explains what the current maturity level of JSI is.

The question of documentation has come up here, and also in the Hermes github repo. Questions there tend to be about JSI generally or outside of the context of RN, but the answers should still be mostly useful to people writing RN native modules. https://github.com/facebook/hermes/issues/43#issuecomment-512558215 is something I wrote early on, which includes a pointer to the JSI header file (which is still the best detailed documentation).

Another useful file is the JSI tests which you can find at https://github.com/facebook/hermes/blob/master/API/jsi/jsi/test/testlib.cpp. This file uses Runtime, HostObject, and HostFunction extensively, but because it's trying to be comprehensive, not everything in there is actually a practice I would recommend. All that code will run with JSC or Hermes.

tomduncalf commented 4 years ago

@mhorowitz thanks very much for the detailed update!

We have developed quite a tight integration between our C++ audio engine (using the JUCE framework) and React Native UI, with features like automatic state synchronisation, so JSI is definitely of interest to us in terms of both making the integration more performant, and cleaner in implementation. I look forward to trying out JSI in the near future!

If you’re interested to learn a bit more about our C++/RN integration, I go into more detail about it in this talk about how we built the ROLI LUMI app with React Native, JUCE and Unity from last year’s Audio Developers Conference: https://m.youtube.com/watch?index=42&v=bsy0-mHcS4Y&list=LLgksgv5Myug8PARo0Q2znaQ

ghost commented 4 years ago

So I've not made any progress figuring out how I'm meant to make a call back to my JavaScript from a native thread using the JSI. Assuming I'm using JSC, it seems to me that I need to acquire the JSGlobalContextRef held by the JSCRuntime object supplied to my JSI functions (as a jsi::Runtime). The obvious problem being the lack of any way of invoking JSGlobalContextRetain.

I don't mean to pollute this discussion but my problem does seem to be on-topic as the JSI seems to lack an API for safely keeping a reference to the JSC context in which my JavaScript lives.

sercand commented 4 years ago

Before JSI, our project was directly accessing to JSC by getting private JSGlobalContextRef from the bridge. I was defining lots of native functions in Rust and registring them to the global context. We have native functions for filesystem, sqlite, HTTP server, zip/unzip, download files for both iOS and Android. After JSI, we have only c++ API with multiple js backend, therefore, we can't use it directly anymore. To solve this, I created a "jsi-c" library which mostly mimics JSCore C API on JSI. Now my rust library links to jsi-c with lots of helper rust macros.

A usage example:

jsi_ffi! {
    pub fn fs_exists(path: String) -> bool {
        PathBuf::from(path).exists()
    }
}

#[no_mangle]
pub unsafe extern "C" fn register_env(ctx: jsi::sys::JSIRuntime) {
    let mynative = jsi::Object::new(ctx);
    mynative.set_fn_property("fs_exists", Some(fs_exists));
    jsi::Object::global(ctx).set_property("$mynative", mynative.into_value());
}

then call register_env function on swift/objc at RCTJavaScriptWillStartExecutingNotification.

My current biggest issue with JSI is it does not have the typed array interface. Javascript Core has it on iOS 10+ and also Hermes has it but JSI has only ArrayBuffer interface. Without a typed array interface, we can't reuse a single typed array for performance reasons and constantly convert between Uint8Array and ArrayBuffer.

elicwhite commented 4 years ago

The Hermes team maintains JSI. You can ask about TypedArray support on the Hermes repo

tmikov commented 4 years ago

Can you clarify what TypedArray functionality is missing from JSI? AFAICT, it is possible to do everything.

acton393 commented 4 years ago

how about make JSI a separated shared lib for community, RN and other libs can depend on it, we can make contribution to JSI

acton393 commented 4 years ago

I made a separation about JSI from react-native and repository is https://github.com/acton393/JSI . The sample is https://github.com/acton393/JSISample which reference on https://github.com/ericlewis/react-native-hostobject-demo

tmikov commented 4 years ago

@acton393 a complication is that any changes in the JSI lib has to be mirrored by changes in the JSI implementations for the different VMs. Facebook is currently maintaining the JSC and Hermes one, and there is at least one for V8 (from Microsoft I believe).

How would the process of adding new functionality work?

acton393 commented 4 years ago

@tmikov JSC VM runtime is ready now (copy from Facebook), iOS sample using JSC runtime next step I will finish V8 runtime for JSI.

I will update here if any changes

ryantrem commented 4 years ago

@mhorowitz Is it possible to define a JavaScript class with JSI? I looked ever jsi.h and a few existing examples I could find, and while it is quite straight forward to define object instances, I couldn't figure out how to define a class. I thought maybe I could just define a function, and then new that function in JavaScript in the same way I could if implemented directly in JavaScript, but that just resulted in an error ("TypeError function is not a constructor").

@oNaiPs it sounds like you were adapting NAPI to JSI, so I'm guessing you may have already solved this problem. We have some existing code that uses NAPI to interop between C++ and JavaScript (which relies on defining JavaScript classes), and we're trying to adapt it to JSI so we can use it in React Native. Any learnings you can share?

mhorowitz commented 4 years ago

@ryantrem JavaScript classes are just syntactic sugar over functions, prototypes, and properties. You can do all that in JSI. The main thing you can't currently do is create a Function with a [[Construct]] internal method. In practice, the only real limitation that creates is you can't call new Foo() on such a function. JS constructor semantics are a bit weird, so it might be simpler just to create objects using Foo(), and have it return an object with an appropriate prototype.

It's pretty common to see people use HostObject when they should instead just use a vanilla JS object, and add HostFunction properties to it. Depending on what you're trying to do with your C++ interop layer, this might be the best approach.

Another option is to use a small JS shim. Create a HostFunction FooHostFunc, and JS like this:

function Foo() { return FooHostFunc.apply(this, arguments); };
var f = new Foo();

If you're trying to differentiate between Foo() and new Foo() in your HostFunction, that's also not going to be possible currently, but the uses cases for that are rare.

ryantrem commented 4 years ago

Thanks @mhorowitz, this approach works great. For reference, here is what I came up with based on your suggestion:

auto code = std::make_shared<const jsi::StringBuffer>("(function() { return TestClass.ctor.apply(this, arguments); })");
auto testClass = jsiRuntime.evaluateJavaScript(std::move(code), "some description").asObject(jsiRuntime);

testClass.setProperty(jsiRuntime, "ctor", jsi::Function::createFromHostFunction(jsiRuntime, jsi::PropNameID::forAscii(jsiRuntime, "TestClass.ctor"), 1, [](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value
{
    auto testObj = thisValue.asObject(runtime);
    testObj.setProperty(runtime, "testProperty1", std::move(arguments[0]));
    return nullptr;
}));

auto testClassPrototype = testClass.getProperty(jsiRuntime, "prototype").asObject(jsiRuntime);
testClassPrototype.setProperty(jsiRuntime, "testProperty2", 55);
testClassPrototype.setProperty(jsiRuntime, "testFunction", jsi::Function::createFromHostFunction(jsiRuntime, jsi::PropNameID::forAscii(jsiRuntime, "testFunction"), 0, [](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value
{
    thisValue.asObject(runtime).setProperty(runtime, "testProperty2", 66);
    return jsi::Value(runtime, jsi::String::createFromAscii(runtime, "this is a test function"));
}));

jsiRuntime.global().setProperty(jsiRuntime, "TestClass", std::move(testClass));

Then in JavaScript I can do this:

const testObj = new TestClass(7);
console.log("TestClass.testProperty1: " + testObj.testProperty1); // prints 7
console.log("TestClass.testProperty2: " + testObj.testProperty2); // prints 55
console.log("TestClass.testFunction(): " + testObj.testFunction()); // prints 'this is a test function'
console.log("TestClass.testProperty2: " + testObj.testProperty2); // prints 66

Regarding this comment:

It's pretty common to see people use HostObject when they should instead just use a vanilla JS object, and add HostFunction properties to it.

Looking over jsi.h, I didn't understand the purpose of HostObject for exactly the reason you state above - everything I wanted to do could be done by creating a jsi::Object and just calling setProperty on it (for values, or functions via HostFunction). The only reason I could think to use HostObject would be if you wanted the storage of the underlying properties to live on the C++ side, or if you wanted all property evaluation to be lazy. In what scenarios would you say HostObject should be used?

mhorowitz commented 4 years ago

That code looks about what I had in mind, glad you made it work.

A nit: evaluateJavaScript is pretty expensive, and it's possible (although not well documented) in resource-constrained environments to package Hermes without the parser/compiler at all, and just use bytecode. For prototyping, it's ok, but in a production environment, I'd include that stub in JS somewhere, and not emit one per "class". If you have many classes, you could write a single JS function like this:

function makeNativeClass(initializer) {
  return function() { return initializer.apply(this, arguments); }
}

and then use it from C++:

// I haven't tested this, so consider it pseudocode
auto initializer = Function::createFromHostFunction(...);
runtime.global().setProperty(runtime, "TestClass",
  runtime.global().getPropertyAsFunction(runtime, "makeNativeClass")
    .call(runtime, initializer));

This avoids runtime calls into the compiler, and avoids per-class JS glue. If you did want to have the instance be a HostObject, then you'd need to change the pattern a bit to create one, but it sounds like you don't.

Which leads to your second question, those are the two clear cases: to associate native data with a JS object (although you can do this with a HostFunction, the pattern is different and less usable), and for lazy proprety evaluation. A subcase of this is when you don't know all the property names in advance.

ryantrem commented 4 years ago

Interesting, thanks for that extra info. Would it be safe to use jsiRuntime.global().getPropertyAsFunction(jsiRuntime, "eval").call(jsiRuntime, code) instead of jsiRuntime.evaluateJavaScript(code, "some description")? I'm asking because we are doing this work in a lower level library below React Native where we don't have an obvious way to include JavaScript other than injecting it via an API like NAPI or JSI.

If you did want to have the instance be a HostObject, then you'd need to change the pattern a bit to create one

While I don't see a need at this point, I'm curious how we could make this work. My understanding is that when we use new, JavaScript creates the object instance, so I'm not sure how you could make this pattern work when we want the object instance to be a HostObject (which presumably needs to be instantiated by the C++ side of things). What would the pattern for this look like?

mhorowitz commented 4 years ago

Would it be safe to use... eval

eval also calls the parser/compiler, so there's not much of a difference. If you really have no other way, then you may not have a choice, and if the code is small, it's probably ok. You could also compile the JS code when building your library, include the bytecode as an asset, and then call evaluateJavaScript on that. That would avoid needing to run the compiler at runtime.

My understanding is that when we use new, JavaScript creates the object instance

As I mentioned, JS constructor semantics are a bit weird. You can see this in plain JS in any engine. JS will create an object which is used as the this of the constructor. If the ctor doesn't return anything, this is the result of new. If the ctor returns an object, new returns that instead:

>> function C() { var o = Object.create({protoprop: 2}); o.prop = 3; return o; }
undefined
>> c = new C()
{ prop: 3 }
>> c.protoprop
2

So if C returned a HostObject, then new C would return it, too. You could do this by changing makeNativeClass to return the result from initializer, for example.

bibinkt commented 4 years ago

Hi,

Is the new architecture [fabric] is ready to use shape? can any one answer?

ryantrem commented 4 years ago

We've been trying to use JSI to integrate Babylon Native into React Native but hit a roadblock when we found that the JSI JSCRuntime implementation doesn't support array buffers. The necessary JSC calls are commented out, even though the version of JSC currently used by React Native supports all these functions (JSValueGetTypedArrayType, JSObjectGetArrayBufferBytesPtr, and JSObjectGetArrayBufferByteLength). Are those comments (and associated commented out code) just out of date? Is there a plan/timeline to enable these functions?

Also, it looks like this (or something very similar) may have been under discussion fairly recently but that discussion seems to be awaiting input from @mhorowitz. cc @bghgary

mhorowitz commented 4 years ago

@ryantrem Based on @tmikov's comment https://github.com/facebook/hermes/issues/182#issuecomment-583179072 I think if you submitted a PR to enable these functions and tested that they work, there's no reason not to accept that.

https://github.com/facebook/hermes/issues/182 is about adding additional functionality to JSI to make TypedArray easier to use and faster, which is related, but enabling ArrayBuffer in JSCRuntime could proceed in parallel.

vonovak commented 4 years ago

Hello folks, I'd like to ask questions that will clarify my (and hopefully other people's too) mental model around JSI.

  1. JSI allows to JS to call C++ code (and other way round). For that it uses a bunch of JavaScriptCore apis as seen in JSCRuntime.cpp. Where is this implementation for Hermes?
  2. Will JSI/Fabric help avoiding some "state duplication" across JS and native? To illustrate what I mean: consider the Switch component which has its state in React / JS but the "true state" lives in UIKit. It's theoretically possible that the two states can get out of sync. RN handles it here using a combo of forceUpdate and imperative calls in componentDidUpdate. Will there be some way to remove this kind of state duplication? Is this part of the goal or is it non-goal? I guess in this case it's not really possible (?) but perhaps it could help in some cases in more complex components (TextInput comes to my mind).
  3. just to clarify, when HostObject is mentioned, is that the term as defined here or is that a JSI-specific term?

Thanks a lot for answering!

mhorowitz commented 4 years ago

Hi @vonovak. Thanks for asking!

  1. The HermesRuntime implementation is in https://github.com/facebook/hermes/blob/master/API/hermes/hermes.cpp.
  2. I'll let someone on the RN team take this one.
  3. I don't think there's a simple answer to this question, but I'll give you some context. The definition you reference is from the 2011 version of the ECMAScript spec, and does not exist in the 2015 and newer versions. The newer versions introduce the term "exotic object": "object that does not have the default behaviour for one or more of the essential internal methods". In the context of JSI, I would generally expect that HostObject refers to this specific type. The name is originally inspired by the 2011 spec name. In modern spec terminology, a HostObject provides the native implementation, via Object::createFromHostObject(), of a particular kind of exotic object.