The js type¶
js is a handle to a live JavaScript value — a DOM node, a fetch Response, a RegExp, a
plain object, or a function. You read, call, and mutate it with ordinary Dream syntax.
At a glance
jsis a handle to a live JavaScript value.- Read, call, and change it with ordinary Dream syntax; it needs a browser or Node host.
fun main(): void {
let doc = js.global.document;
let el = doc.getElementById("app");
el.textContent = "hello";
el.classList.add("a", "b", "c");
let n: int = el.childNodes.length;
System.println("children: " + n);
}
How js values work¶
js is a real static type, but Dream does no member resolution on it. Any .name,
.name(...), [key], or call type-checks; whether the member exists is decided at runtime by the
JS host. Dynamic operations return js, so chains like el.classList.add(...) just work.
You leave the dynamic world at a typed boundary — assigning to a typed variable, passing a typed argument, or returning a typed value — where Dream converts automatically:
A js value is not a Dream heap object, but its handle is reference-counted the same way heap values are: when the last Dream owner drops, the JS value can be collected. See Memory Management.
You do not call a manual release API — scope exit, reassignment, and container teardown free handles automatically.
Getting a js value¶
| Entry point | Gives you |
|---|---|
js.global |
globalThis — e.g. js.global.document, js.global.fetch(...) |
js.global(name) |
globalThis[name], for a runtime-only name |
js.object() |
a fresh empty {} |
js.array() |
a fresh empty [] |
js.null / js.undefined |
the JS null / undefined values as js handles |
js.func(handler) / js.func0(handler) |
wrap a Dream function as a JS callable — see Callbacks |
Reading, writing, and calling¶
let el = js.global.document.getElementById("app");
let cls: js = el.className;
el.className = "highlighted";
el.classList.add("a", "b", "c");
let first = el.children[0];
el.children[0] = replacement;
Passing values to JS¶
| Dream value | Crosses as |
|---|---|
int / long / double / bool / string |
itself |
another js |
passed through |
an array of the above (int[], string[], js[], …) |
a JS array |
a Dream function (fun(...)) |
a JS callable — see Callbacks |
a struct / class |
a deep copy into a plain JS object |
A union or List<T> is not marshalable directly — convert to an array or struct field first.
// js.global.send(my_list); // error: List is not passed to js
// js.global.send(my_union); // error: union is not passed to js
Structs and classes¶
Passing a struct or class to JS deep-copies it into a plain object (nested fields and arrays
included). Fields that cannot cross (maps, interfaces, function values) are left off:
class Point {
public x: int;
public y: int;
public constructor(x: int, y: int) {
this.x = x;
this.y = y;
}
}
js.global.render(Point(3, 4)); // -> render({ x: 3, y: 4 })
Assigning a js object to a class- or value-struct-typed variable rebuilds it by reading
each declared field — the constructor is not called. Classes allocate a heap instance; value
structs fill the destination slot in place:
class Point {
public x: int;
public y: int;
public constructor(x: int, y: int) {
this.x = x;
this.y = y;
}
}
let p: Point = js.global.originPoint();
Getting values back out¶
A result from JS stays a js value until a typed binding, argument, or return converts it. Or
convert explicitly:
| Method | Converts to |
|---|---|
to_int() / to_double() / to_bool() / to_str() |
the matching Dream primitive |
is_null() |
true if the value is null or undefined |
Awaiting JS Promises¶
Await a JS Promise directly — it resolves to Option<js>: Some(value) on success, None
when the Promise rejected or resolved with null/undefined. A rejection reason is printed on
the console. Typed extern async fun results stop the program on rejection instead; see
Awaiting JavaScript promises.
async fun load(): void {
let resp = js.global.fetch("/api").await;
switch (resp) {
Some(r) => {
let ok: bool = r.ok;
System.println("ok = " + ok);
}
None => System.println("request failed"),
}
}
await may appear anywhere in an async function, including loops and branches.
Where it runs¶
js needs a JavaScript host (browser or Node). Referencing js APIs when targeting native is a compile error.