The `js::Value` class is used to represent live values in JavaScript. It supports a number of operations and provides convenient conversions to and from native types.

### Example Code

The example code on this page uses the following `monster` object defined in `page.html`:

```html
<html>
  <head>
    <script type="text/javascript">
      // Our JavaScript object "monster"
      var monster = {
        name: "Vampire",
        damage: 12,
        level: "7",
        loot: ["gold", "fang"]
      };
    </script>
  </head>
  <body>
    <div id="hud"></div>
  </body>
</html>
```

## Lifetimes

### Safe Handles with Graceful Degradation

A `js::Value` is a safe, RAII handle that points to a live JavaScript value— you can store it in your own objects and use it later without crashes when the page goes away. If an operation fails, the library returns an error and fails gracefully instead of throwing a C++ exception.

### Garbage Collection

While handles are held, the JS garbage collector will not collect the underlying JavaScript value. Try not to hold onto unneeded handles to keep memory growth of the heap low.

### Not Thread-Safe

Most operations must be performed on the Renderer thread (the thread you called `Renderer::Create()` or `App::Create()` on). (Copying, moving, and destroying handles are safe from any thread.)

> 🚧 Handles and Contexts Don't Persist Between Page Navigations
>
> A handle keeps its JavaScript value from being garbage-collected but it doesn't keep its parent page alive. When a page navigates away, existing handles and contexts are no longer valid.

## Handle Validity

### Handle States

Handles can be in one of three states:

| State | When a handle is in it | `if (val)` | Calls on it |
| :--- | :--- | :--- | :--- |
| Valid | Points to a JS value on a live page | `true` | Work normally |
| Empty | An operation failed, or the handle was never initialized or was moved from | `false` | Do nothing |
| Gone | Its page navigated away, its frame was removed, or its View was destroyed | `false` | Do nothing |

Operations are safe on all three states (the API never throws exceptions even during chained operations on invalid handles)— error-checking is optional.

### Working With Handles

You can cache a `js::Value` handle across calls to interact with a page object over time:

```cpp
class MyApp : public LoadListener {
 public:
  // Inherited from LoadListener::OnDOMReady:
  void OnDOMReady(View* caller, uint64_t frame_id, bool is_main_frame,
                  const String& url) override {
    if (!is_main_frame)
      return;

    // Get the JS context for a View
    js::Context ctx(caller);

    // Cache a js::Value handle "monster_" to our page's "monster" object.
    //
    // NOTE: This handle's page is gone after each page navigation so
    //       we must re-initialize it after each "DOMReady".
    //
    // NOTE: This will prevent the JavaScript value on the page from being
    //       garbage collected but it will NOT keep the page / View alive.
    //
    monster_ = ctx["monster"];
  }

  // Called at some point during game execution:
  void UpdateHUD() {
    // Get 'damage' from our live 'monster' object as "std::optional<double>"
    //
    // NOTE: This will only succeed if all of the following are true:
    //         - the monster_ js::Value handle is valid
    //         - the property "damage" exists
    //         - the property can be converted to a double
    //
    // NOTE: The JS and DOM APIs are designed with graceful degradation in mind:
    //       a failed read returns std::nullopt or an error, never throws.
    //
    if (auto dmg = monster_["damage"].Maybe<double>()) {
      // Use the optional value as a "double"
      DrawDamage(*dmg);
    }
  }

  void DrawDamage(double damage) {
    // ...
  }

 private:
  js::Value monster_;  // empty js::Value handle
};
```

## Creating Values

You can create JavaScript values in C++ using `js::Context`:

```cpp
js::Value settings = ctx.MakeObject();
settings["volume"] = 5;
settings["muted"] = false;
ctx["applySettings"](settings);

js::Value slots = ctx.MakeArray({ ctx.Make("slot1"), ctx.Make("slot2") });

js::Value defaults =
    js::OrEmpty(ctx.MakeFromJSON(R"({"volume": 5, "muted": false})"));
ctx["defaults"] = defaults;
```

Call `ctx.Make()` to convert a C++ value into a `js::Value`. Use `MakeObject()` to create an empty object, `MakeArray()` to create an array, and `MakeFromJSON()` to parse a JSON string.

For the full list of supported types, see [Passing Data Across the Bridge](/docs/2.0/passing-data-across-the-bridge).

## Type Inspection

You can inspect the underlying JavaScript type of a value with query methods:

```cpp
js::Value loot = monster_["loot"];
if (loot.IsArray())
  Use(loot);

if (monster_["boss"].Get().IsNullish())  // missing, undefined, or null
  Log("not a boss");
```

Methods such as `IsNumber()`, `IsString()`, `IsArray()`, `IsObject()`, and `IsCallable()` check whether a value matches a specific type.

The `IsNullish()` method returns `true` if the value is either `js::null` or `js::undefined`.

## Type Conversions

### Strict Conversions

You can convert values to C++ types using `Or()`, `Maybe<T>()`, or `To<T>()`:

```cpp
double damage = monster_["damage"].Or(0.0);                       // 12
std::optional<double> armor = monster_["armor"].Maybe<double>();  // nullopt
js::Result<std::string> name = monster_["name"].To<std::string>();
```

These methods use *strict* type-checking— they require the JavaScript value to match the requested C++ type exactly. The string `"7"` does *not* convert to a number.

The three methods differ only in how they report failures. `Or()` returns a fallback value, `Maybe<T>()` returns `std::nullopt`, and `To<T>()` returns a `js::Result<T>` containing an error message.

You should use `Or()` for most property reads where you expect the handle to be valid and convertible.

### JavaScript Conversions

To convert values using JavaScript's implicit conversion rules, you should instead call `ToNumber()`, `ToString()`, `ToBoolean()`, or `ToJSON()` directly on a `js::Value`:

```cpp
js::Value level = monster_["level"];               // Raw value is "7" (string)

double strict = level.Or(0.0);                     // FAIL: 0.0 (strict)
double implicit = level.ToNumber().value_or(0.0);  // SUCCESS: 7.0 (implicit)
```

## Object Properties

### Reading Properties

You can check for the existence of a property using `Has()` and read properties using `operator[]`:

```cpp
// Check if "monster" has object property "boss"
if (monster_.Has("boss"))
  Use(monster_["boss"]); // (won't be reached, doesn't exist)

// monster.boss doesn't exist (see code at top), so this falls back to "0.0"
// instead of throwing an exception.
double boss_level = monster_["boss"]["level"].Or(0.0);
```

Chained reads fail safely like JavaScript optional chaining, so reading a property on a missing object returns an empty `js::Value` instead of throwing an exception. 

### Writing Properties

Assign directly to a property to write to it:

```cpp
monster_["name"] = "Vampire Lord";
monster_["damage"] = 20;
monster_["boss"] = js::null;
```

Native C++ values convert automatically on assignment. Failed writes are ignored silently (such as when a setter throws). To detect failures, use `SetProperty()`, which returns a `js::Result` with explicit error values.

## Iteration

To iterate over an array or an object, convert it to a standard C++ container:

```cpp
auto loot = js::OrEmpty(monster_["loot"].To<std::vector<js::Value>>());
for (js::Value& item : loot)
  Log(item.Or(""));  // "gold", then "fang"

auto fields = js::OrEmpty(monster_.To<std::map<std::string, js::Value>>());
```

Converting an array to `std::vector<js::Value>` lets you loop over its elements. Converting an object to `std::map<std::string, js::Value>` lets you walk its key-value pairs. In both cases, `js::OrEmpty` returns an empty container if the conversion fails.

## Passing Values Between Pages

To pass data between pages, copy it to the destination context using JSON or native types:

```cpp
// The page in another View (eg, an in-game bestiary):
js::Context bestiary(bestiary_view.get());

std::string json = monster_.ToJSON().value_or("null");
bestiary["monster"] = js::OrEmpty(bestiary.MakeFromJSON(json));
```

A `js::Value` belongs to the page that created it— native code can pass a handle directly only when both pages are frames of the same top-level page and share the exact same origin. Values from another View are always refused.

Any operation that receives a value from an incompatible page fails with a TypeError whose code is `ULJS_CROSS_CONTEXT` (see [JavaScript Errors and Diagnostics](/docs/2.0/javascript-errors-and-diagnostics)).

## Ownership Cycles

> 🚧 Circular References Prevent Garbage Collection
>
> When a bound native class instance stores a `js::Value` pointing back to its own JavaScript object, neither can be garbage-collected while the page is alive. To break the cycle, clear the handle in an explicit close method or store a `js::WeakValue` instead (see [Exposing Native Classes](/docs/2.0/exposing-native-classes)).

## Weak Values

A `js::WeakValue` holds a reference to a JavaScript object without preventing garbage collection:

```cpp
js::WeakValue cached(monster_);

// Later:
if (js::Value strong = cached.Lock())
  UseCached(strong);
else
  RebuildCache();
```

This non-owning reference is useful for observing JavaScript values without keeping them alive.

Call `Lock()` to obtain a valid `js::Value` for the object. If the object has been garbage-collected or its page navigated away, `Lock()` returns an empty handle.

> 🚧 JavaScript Callbacks Require Strong References
>
> Never use `js::WeakValue` as the only reference to a JavaScript callback. If nothing on the page holds the function, the garbage collector reclaims it.
