///|
#external
pub type Value
///|
pub fn[T] Value::cast_from(value : T) -> Value = "%identity"
///|
pub fn[T] Value::cast(self : Value) -> T = "%identity"
///|
pub extern "js" fn Value::to_string(self : Value) -> String = "(self) => self.toString()"
///|
pub impl Show for Value with output(self, logger) {
logger.write_string(self.to_string())
}
///|
pub let globalThis : Value = get_globalThis()
///|
pub fn[T] get_with_string(self : Value, key : String) -> T {
self.get_ffi(Value::cast_from(key)).cast()
}
///|
pub fn[T] get_with_symbol(self : Value, key : Symbol) -> T {
self.get_ffi(Value::cast_from(key)).cast()
}
///|
pub fn[T] get_with_index(self : Value, index : Int) -> T {
self.get_ffi(Value::cast_from(index)).cast()
}
///|
pub fn[T] set_with_string(self : Value, key : String, value : T) -> Unit {
self.set_ffi(Value::cast_from(key), Value::cast_from(value))
}
///|
pub fn[T] set_with_symbol(self : Value, key : Symbol, value : T) -> Unit {
self.set_ffi(Value::cast_from(key), Value::cast_from(value))
}
///|
pub fn[T] set_with_index(self : Value, index : Int, value : T) -> Unit {
self.set_ffi(Value::cast_from(index), Value::cast_from(value))
}
///|
/// `self(...args)`
pub fn[Arg, Result] Value::apply(self : Value, args : Array[Arg]) -> Result {
self.apply_self_ffi(Value::cast_from(args)).cast()
}
///|
/// `self[key](...args)`
pub fn[Arg, Result] Value::apply_with_string(
self : Value,
key : String,
args : Array[Arg],
) -> Result {
self.apply_ffi(Value::cast_from(key), Value::cast_from(args)).cast()
}
///|
/// `self[key](...args)`
pub fn[Arg, Result] Value::apply_with_symbol(
self : Value,
key : Symbol,
args : Array[Arg],
) -> Result {
self.apply_ffi(Value::cast_from(key), Value::cast_from(args)).cast()
}
///|
/// `self[index](...args)`
pub fn[Arg, Result] Value::apply_with_index(
self : Value,
index : Int,
args : Array[Arg],
) -> Result {
self.apply_ffi(Value::cast_from(index), Value::cast_from(args)).cast()
}
///|
/// `new self(...args)`
pub fn[Arg, Result] Value::new(self : Value, args : Array[Arg]) -> Result {
self.new_self_ffi(Value::cast_from(args)).cast()
}
///|
/// `new self[key](...args)`
pub fn[Arg, Result] Value::new_with_string(
self : Value,
key : String,
args : Array[Arg],
) -> Result {
self.new_ffi(Value::cast_from(key), Value::cast_from(args)).cast()
}
///|
/// `new self[key](...args)`
pub fn[Arg, Result] Value::new_with_symbol(
self : Value,
key : Symbol,
args : Array[Arg],
) -> Result {
self.new_ffi(Value::cast_from(key), Value::cast_from(args)).cast()
}
///|
/// `new self[index](...args)`
pub fn[Arg, Result] Value::new_with_index(
self : Value,
index : Int,
args : Array[Arg],
) -> Result {
self.new_ffi(Value::cast_from(index), Value::cast_from(args)).cast()
}
///|
pub fn Value::from_json(json : Json) -> Value raise {
@json.from_json(json)
}
///|
pub impl @json.FromJson for Value with from_json(json : Json, path) {
match json {
String(s) => Value::cast_from(s)
Number(n, ..) => Value::cast_from(n)
False => Value::cast_from(false)
True => Value::cast_from(true)
Null => Value::null()
Array(xs) => {
let acc = Array::new(capacity=xs.length())
for x in xs {
acc.push((@json.from_json(x, path~) : Value))
}
Value::cast_from(acc)
}
Object(kvs) => {
let acc = Object::new()
for k, v in kvs {
acc.inner().set_with_string(k, (@json.from_json(v, path~) : Value))
}
acc.inner()
}
}
}
///|
pub fn Value::from_json_string(str : String) -> Value raise {
Error_::wrap(fn() { Value::from_json_string_ffi(str) })
}
///|
extern "js" fn Value::from_json_string_ffi(str : String) -> Value = "JSON.parse"
///|
pub fn Value::to_json_string(self : Value) -> String raise {
Error_::wrap(fn() { self.to_json_string_ffi() })
}
///|
pub fn Value::to_json(self : Value) -> Json raise {
@json.parse(self.to_json_string())
}
///|
extern "js" fn Value::to_json_string_ffi(self : Value) -> Value =
#| (self) => JSON.stringify(self)
///|
pub extern "js" fn is_bool(self : Value) -> Bool =
#| (value) => Object.is(typeof value, 'boolean')
///|
pub extern "js" fn is_null(self : Value) -> Bool =
#| (n) => Object.is(n, null)
///|
pub extern "js" fn is_undefined(self : Value) -> Bool =
#| (n) => Object.is(n, undefined)
///|
pub extern "js" fn is_number(self : Value) -> Bool =
#| (n) => Object.is(typeof n, "number")
///|
pub extern "js" fn is_string(self : Value) -> Bool =
#| (n) => Object.is(typeof n, "string")
///|
pub extern "js" fn is_object(self : Value) -> Bool =
#| (n) => Object.is(typeof n, "object")
///|
pub extern "js" fn is_symbol(self : Value) -> Bool =
#| (n) => Object.is(typeof n, "symbol")
///|
extern "js" fn get_globalThis() -> Value =
#| () => globalThis
///|
extern "js" fn get_ffi(self : Value, key : Value) -> Value =
#| (obj, key) => obj[key]
///|
extern "js" fn set_ffi(self : Value, key : Value, value : Value) =
#| (obj, key, value) => { obj[key] = value }
///|
extern "js" fn apply_ffi(self : Value, key : Value, args : Value) -> Value =
#| (self, key, args) => self[key](...args)
///|
extern "js" fn apply_self_ffi(self : Value, args : Value) -> Value =
#| (self, args) => self(...args)
///|
extern "js" fn new_ffi(self : Value, key : Value, args : Value) -> Value =
#| (self, key, args) => new self[key](...args)
///|
extern "js" fn new_self_ffi(self : Value, args : Value) -> Value =
#| (self, args) => new self(...args)
///|
extern "js" fn Value::null() -> Value =
#| () => null
///|
extern "js" fn Value::undefined() -> Value =
#| () => undefined
///| @param self The constructor function that accepts this as the first argument
pub extern "js" fn extends(self : Value, parent_constructor : Value) -> Value =
#|(f, parent) => {
#| return class extends parent {
#| constructor(...args) {
#| super();
#| f(this, ...args);
#| }
#| }
#|}