feat: 支持 Date/Map/Set 成员方法
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::native::NativeResult;
|
||||
use crate::vm::Vm;
|
||||
|
||||
pub fn boolean_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let bool_val = if args.len() > 1 {
|
||||
let arg = vm.reg(args[1]);
|
||||
if arg.is_undefined() || arg.is_null() {
|
||||
false
|
||||
} else if arg.is_bool() {
|
||||
arg.as_bool()
|
||||
} else if arg.is_string() {
|
||||
let s = vm
|
||||
.kernel()
|
||||
.string_forge()
|
||||
.lookup(arg.as_string_index())
|
||||
.unwrap_or_default();
|
||||
!s.is_empty()
|
||||
} else if arg.is_object() {
|
||||
true
|
||||
} else if arg.is_int() {
|
||||
arg.as_int() != 0
|
||||
} else if arg.is_double() {
|
||||
arg.as_double() != 0.0
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let boolean_proto = vm.kernel().builtin_world().boolean_proto.as_ptr() as *mut JsObject;
|
||||
let is_ctor = if this_val.is_object() {
|
||||
let ptr = this_val.as_js_object_ptr();
|
||||
if ptr.is_null() {
|
||||
false
|
||||
} else {
|
||||
let proto_ptr = unsafe { (*ptr).proto().as_js_object_ptr() };
|
||||
!proto_ptr.is_null() && std::ptr::eq(proto_ptr, boolean_proto)
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if !is_ctor {
|
||||
return Ok(JsValue::bool(bool_val));
|
||||
}
|
||||
|
||||
let obj = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
obj.push_prop(JsValue::bool(bool_val));
|
||||
Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn boolean_prototype_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.valueOf called on non-Boolean object",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let boolean_proto = vm.kernel().builtin_world().boolean_proto.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = obj.proto().as_js_object_ptr();
|
||||
if proto_ptr.is_null() || !std::ptr::eq(proto_ptr, boolean_proto) {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.valueOf called on non-Boolean object",
|
||||
));
|
||||
}
|
||||
let val = obj.get_prop_at(0);
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn boolean_prototype_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.toString called on non-Boolean object",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let boolean_proto = vm.kernel().builtin_world().boolean_proto.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = obj.proto().as_js_object_ptr();
|
||||
if proto_ptr.is_null() || !std::ptr::eq(proto_ptr, boolean_proto) {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Boolean.prototype.toString called on non-Boolean object",
|
||||
));
|
||||
}
|
||||
let val = obj.get_prop_at(0);
|
||||
let is_true = if val.is_bool() {
|
||||
val.as_bool()
|
||||
} else {
|
||||
!val.is_null() && !val.is_undefined()
|
||||
};
|
||||
if is_true {
|
||||
Ok(vm.intern("true"))
|
||||
} else {
|
||||
Ok(vm.intern("false"))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,640 @@
|
||||
use chrono::{DateTime, Datelike, NaiveDate, NaiveDateTime, Timelike, Utc};
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::coercion;
|
||||
use crate::native::NativeResult;
|
||||
use crate::vm::Vm;
|
||||
|
||||
fn get_timestamp(obj: &JsObject) -> f64 {
|
||||
obj.get_prop_at(0).as_double()
|
||||
}
|
||||
|
||||
fn set_timestamp(obj: &mut JsObject, ms: f64) {
|
||||
obj.set_prop_at(0, JsValue::float(ms));
|
||||
}
|
||||
|
||||
fn is_date(vm: &Vm, obj: &JsObject) -> bool {
|
||||
let date_proto = vm.kernel().builtin_world().date_proto.as_ptr() as *mut JsObject;
|
||||
if date_proto.is_null() {
|
||||
return false;
|
||||
}
|
||||
let proto_ptr = obj.proto().as_js_object_ptr();
|
||||
if proto_ptr.is_null() {
|
||||
return false;
|
||||
}
|
||||
std::ptr::eq(proto_ptr, date_proto)
|
||||
}
|
||||
|
||||
fn ensure_date(vm: &mut Vm, obj: &JsObject) -> NativeResult {
|
||||
if !is_date(vm, obj) {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
fn dt_from_ms(ms: f64) -> Option<DateTime<Utc>> {
|
||||
if !ms.is_finite() {
|
||||
return None;
|
||||
}
|
||||
DateTime::from_timestamp_millis(ms as i64)
|
||||
}
|
||||
|
||||
fn naive_from_ms(ms: f64) -> Option<NaiveDateTime> {
|
||||
if !ms.is_finite() {
|
||||
return None;
|
||||
}
|
||||
dt_from_ms(ms).map(|dt| dt.naive_utc())
|
||||
}
|
||||
|
||||
pub fn date_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let is_ctor_call = this_val.is_object() && {
|
||||
let ptr = this_val.as_js_object_ptr();
|
||||
if ptr.is_null() {
|
||||
false
|
||||
} else {
|
||||
let date_proto = vm.kernel().builtin_world().date_proto.as_ptr() as *mut JsObject;
|
||||
if date_proto.is_null() {
|
||||
false
|
||||
} else {
|
||||
let obj = unsafe { &*ptr };
|
||||
let proto_ptr = obj.proto().as_js_object_ptr();
|
||||
if proto_ptr.is_null() {
|
||||
false
|
||||
} else {
|
||||
std::ptr::eq(proto_ptr, date_proto)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let timestamp = if args.len() < 2 {
|
||||
Utc::now().timestamp_millis() as f64
|
||||
} else {
|
||||
let val = vm.reg(args[1]);
|
||||
if val.is_string() {
|
||||
let s = vm
|
||||
.kernel()
|
||||
.string_forge()
|
||||
.lookup(val.as_string_index())
|
||||
.unwrap_or_default();
|
||||
let formats = ["%Y-%m-%dT%H:%M:%S%.fZ", "%Y-%m-%dT%H:%M:%S%.f"];
|
||||
let mut ts = f64::NAN;
|
||||
for fmt in &formats {
|
||||
if let Ok(ndt) = NaiveDateTime::parse_from_str(&s, fmt) {
|
||||
ts = ndt.and_utc().timestamp_millis() as f64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ts.is_nan() {
|
||||
if let Ok(nd) = NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
|
||||
if let Some(ndt) = nd
|
||||
.and_hms_opt(0, 0, 0)
|
||||
.and_then(|n| n.and_local_timezone(Utc).earliest())
|
||||
{
|
||||
ts = ndt.timestamp_millis() as f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
ts
|
||||
} else if val.is_int() || val.is_double() {
|
||||
if val.is_int() {
|
||||
val.as_int() as f64
|
||||
} else {
|
||||
val.as_double()
|
||||
}
|
||||
} else if val.is_object() && {
|
||||
let ptr = val.as_js_object_ptr();
|
||||
if ptr.is_null() {
|
||||
false
|
||||
} else {
|
||||
is_date(vm, unsafe { &*ptr })
|
||||
}
|
||||
} {
|
||||
let obj = unsafe { &*val.as_js_object_ptr() };
|
||||
get_timestamp(obj)
|
||||
} else {
|
||||
let y =
|
||||
coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as i32;
|
||||
let m = if args.len() > 2 {
|
||||
coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let d = if args.len() > 3 {
|
||||
coercion::to_number(vm.reg(args[3]), vm.kernel().string_forge().as_ref()) as u32
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let h = if args.len() > 4 {
|
||||
coercion::to_number(vm.reg(args[4]), vm.kernel().string_forge().as_ref()) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let min = if args.len() > 5 {
|
||||
coercion::to_number(vm.reg(args[5]), vm.kernel().string_forge().as_ref()) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let sec = if args.len() > 6 {
|
||||
coercion::to_number(vm.reg(args[6]), vm.kernel().string_forge().as_ref()) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let ms = if args.len() > 7 {
|
||||
coercion::to_number(vm.reg(args[7]), vm.kernel().string_forge().as_ref()) as u32
|
||||
} else {
|
||||
0
|
||||
};
|
||||
NaiveDate::from_ymd_opt(y, m + 1, d)
|
||||
.and_then(|nd| {
|
||||
nd.and_hms_milli_opt(h, min, sec, ms)
|
||||
.and_then(|ndt| ndt.and_local_timezone(Utc).earliest())
|
||||
})
|
||||
.map(|dt| dt.timestamp_millis() as f64)
|
||||
.unwrap_or(f64::NAN)
|
||||
}
|
||||
};
|
||||
|
||||
if !is_ctor_call {
|
||||
let s = if timestamp.is_finite() {
|
||||
dt_from_ms(timestamp)
|
||||
.map(|dt| dt.to_rfc2822())
|
||||
.unwrap_or_else(|| "Invalid Date".to_string())
|
||||
} else {
|
||||
"Invalid Date".to_string()
|
||||
};
|
||||
return Ok(vm.intern(&s));
|
||||
}
|
||||
|
||||
let mut obj = JsObject::new_empty(
|
||||
EMPTY_SHAPE_ID,
|
||||
JsValue::from_js_object(vm.kernel().builtin_world().date_proto.as_ptr() as *mut JsObject),
|
||||
);
|
||||
obj.set_prop_at(0, JsValue::float(timestamp));
|
||||
|
||||
let ptr = vm.epoch().alloc(obj);
|
||||
Ok(JsValue::from_js_object(ptr))
|
||||
}
|
||||
|
||||
pub fn date_now(_vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
Ok(JsValue::float(Utc::now().timestamp_millis() as f64))
|
||||
}
|
||||
|
||||
pub fn date_parse(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let val = vm.reg(args[1]);
|
||||
if !val.is_string() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let s = vm
|
||||
.kernel()
|
||||
.string_forge()
|
||||
.lookup(val.as_string_index())
|
||||
.unwrap_or_default();
|
||||
let formats = ["%Y-%m-%dT%H:%M:%S%.fZ", "%Y-%m-%dT%H:%M:%S%.f"];
|
||||
let mut ts = f64::NAN;
|
||||
for fmt in &formats {
|
||||
if let Ok(ndt) = NaiveDateTime::parse_from_str(&s, fmt) {
|
||||
ts = ndt.and_utc().timestamp_millis() as f64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ts.is_nan() {
|
||||
if let Ok(nd) = NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
|
||||
if let Some(ndt) = nd
|
||||
.and_hms_opt(0, 0, 0)
|
||||
.and_then(|n| n.and_local_timezone(Utc).earliest())
|
||||
{
|
||||
ts = ndt.timestamp_millis() as f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
|
||||
pub fn date_utc(_vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
Ok(JsValue::float(f64::NAN))
|
||||
}
|
||||
|
||||
macro_rules! make_getter {
|
||||
($name:ident, $f:expr, $df:expr) => {
|
||||
pub fn $name(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float($df));
|
||||
}
|
||||
match dt_from_ms(ms) {
|
||||
Some(dt) => Ok(JsValue::float(($f)(dt))),
|
||||
None => Ok(JsValue::float($df)),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! make_utc_getter {
|
||||
($name:ident, $f:expr, $df:expr) => {
|
||||
pub fn $name(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float($df));
|
||||
}
|
||||
match naive_from_ms(ms) {
|
||||
Some(ndt) => Ok(JsValue::float(($f)(ndt))),
|
||||
None => Ok(JsValue::float($df)),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
make_getter!(
|
||||
date_get_time,
|
||||
|dt: DateTime<Utc>| dt.timestamp_millis() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_getter!(
|
||||
date_get_full_year,
|
||||
|dt: DateTime<Utc>| dt.year() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_getter!(
|
||||
date_get_month,
|
||||
|dt: DateTime<Utc>| dt.month0() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_getter!(date_get_date, |dt: DateTime<Utc>| dt.day() as f64, f64::NAN);
|
||||
make_getter!(
|
||||
date_get_day,
|
||||
|dt: DateTime<Utc>| dt.weekday().num_days_from_sunday() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_getter!(
|
||||
date_get_hours,
|
||||
|dt: DateTime<Utc>| dt.hour() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_getter!(
|
||||
date_get_minutes,
|
||||
|dt: DateTime<Utc>| dt.minute() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_getter!(
|
||||
date_get_seconds,
|
||||
|dt: DateTime<Utc>| dt.second() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_getter!(
|
||||
date_get_milliseconds,
|
||||
|dt: DateTime<Utc>| dt.timestamp_subsec_millis() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
|
||||
make_utc_getter!(
|
||||
date_get_utc_full_year,
|
||||
|ndt: NaiveDateTime| ndt.date().year() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_utc_getter!(
|
||||
date_get_utc_month,
|
||||
|ndt: NaiveDateTime| ndt.date().month0() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_utc_getter!(
|
||||
date_get_utc_date,
|
||||
|ndt: NaiveDateTime| ndt.date().day() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_utc_getter!(
|
||||
date_get_utc_day,
|
||||
|ndt: NaiveDateTime| ndt.date().weekday().num_days_from_sunday() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_utc_getter!(
|
||||
date_get_utc_hours,
|
||||
|ndt: NaiveDateTime| ndt.time().hour() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_utc_getter!(
|
||||
date_get_utc_minutes,
|
||||
|ndt: NaiveDateTime| ndt.time().minute() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_utc_getter!(
|
||||
date_get_utc_seconds,
|
||||
|ndt: NaiveDateTime| ndt.time().second() as f64,
|
||||
f64::NAN
|
||||
);
|
||||
make_utc_getter!(
|
||||
date_get_utc_milliseconds,
|
||||
|ndt: NaiveDateTime| ndt.time().nanosecond() as f64 / 1_000_000.0,
|
||||
f64::NAN
|
||||
);
|
||||
|
||||
pub fn date_get_timezone_offset(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let offset_min = local_offset_minutes();
|
||||
Ok(JsValue::float(offset_min as f64))
|
||||
}
|
||||
|
||||
fn local_offset_minutes() -> i32 {
|
||||
chrono::Local::now().offset().local_minus_utc() / 60
|
||||
}
|
||||
|
||||
fn get_opt_arg(vm: &Vm, args: &[u8], idx: usize, default: u32) -> u32 {
|
||||
if args.len() > idx {
|
||||
coercion::to_number(vm.reg(args[idx]), vm.kernel().string_forge().as_ref()) as u32
|
||||
} else {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
pub fn date_set_time(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let val = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref())
|
||||
} else {
|
||||
f64::NAN
|
||||
};
|
||||
set_timestamp(obj, val);
|
||||
Ok(JsValue::float(val))
|
||||
}
|
||||
|
||||
pub fn date_set_full_year(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(args[1]);
|
||||
let v = coercion::to_number(val, vm.kernel().string_forge().as_ref());
|
||||
let raw = vm.reg(args[0]);
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let dt = match dt_from_ms(ms) {
|
||||
Some(d) => d,
|
||||
None => return Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let m = get_opt_arg(vm, args, 2, dt.month0());
|
||||
let d = get_opt_arg(vm, args, 3, dt.day0());
|
||||
let nd = dt
|
||||
.with_year(v as i32)
|
||||
.and_then(|x| x.with_month0(m))
|
||||
.and_then(|x| x.with_day0(d))
|
||||
.unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
set_timestamp(obj, ts);
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_month(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(args[1]);
|
||||
let v = coercion::to_number(val, vm.kernel().string_forge().as_ref());
|
||||
let raw = vm.reg(args[0]);
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let dt = match dt_from_ms(ms) {
|
||||
Some(d) => d,
|
||||
None => return Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let d = get_opt_arg(vm, args, 2, dt.day0());
|
||||
let nd = dt
|
||||
.with_month0(v as u32)
|
||||
.and_then(|x| x.with_day0(d))
|
||||
.unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
set_timestamp(obj, ts);
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_date(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(args[1]);
|
||||
let v = coercion::to_number(val, vm.kernel().string_forge().as_ref());
|
||||
let raw = vm.reg(args[0]);
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let dt = match dt_from_ms(ms) {
|
||||
Some(d) => d,
|
||||
None => return Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let nd = dt.with_day0(v as u32).unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
set_timestamp(obj, ts);
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_hours(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(args[1]);
|
||||
let v = coercion::to_number(val, vm.kernel().string_forge().as_ref());
|
||||
let raw = vm.reg(args[0]);
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let dt = match dt_from_ms(ms) {
|
||||
Some(d) => d,
|
||||
None => return Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let min = get_opt_arg(vm, args, 2, dt.minute());
|
||||
let sec = get_opt_arg(vm, args, 3, dt.second());
|
||||
let ms_arg = get_opt_arg(vm, args, 4, dt.timestamp_subsec_millis());
|
||||
let nd = dt
|
||||
.with_hour(v as u32)
|
||||
.and_then(|x| x.with_minute(min))
|
||||
.and_then(|x| x.with_second(sec))
|
||||
.and_then(|x| x.with_nanosecond(ms_arg * 1_000_000))
|
||||
.unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
set_timestamp(obj, ts);
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_minutes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(args[1]);
|
||||
let v = coercion::to_number(val, vm.kernel().string_forge().as_ref());
|
||||
let raw = vm.reg(args[0]);
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let dt = match dt_from_ms(ms) {
|
||||
Some(d) => d,
|
||||
None => return Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let sec = get_opt_arg(vm, args, 2, dt.second());
|
||||
let ms_arg = get_opt_arg(vm, args, 3, dt.timestamp_subsec_millis());
|
||||
let nd = dt
|
||||
.with_minute(v as u32)
|
||||
.and_then(|x| x.with_second(sec))
|
||||
.and_then(|x| x.with_nanosecond(ms_arg * 1_000_000))
|
||||
.unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
set_timestamp(obj, ts);
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_seconds(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(args[1]);
|
||||
let v = coercion::to_number(val, vm.kernel().string_forge().as_ref());
|
||||
let raw = vm.reg(args[0]);
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let dt = match dt_from_ms(ms) {
|
||||
Some(d) => d,
|
||||
None => return Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let ms_arg = get_opt_arg(vm, args, 2, dt.timestamp_subsec_millis());
|
||||
let nd = dt
|
||||
.with_second(v as u32)
|
||||
.and_then(|x| x.with_nanosecond(ms_arg * 1_000_000))
|
||||
.unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
set_timestamp(obj, ts);
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
pub fn date_set_milliseconds(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let val = vm.reg(args[1]);
|
||||
let v = coercion::to_number(val, vm.kernel().string_forge().as_ref());
|
||||
let raw = vm.reg(args[0]);
|
||||
let obj = unsafe { &mut *raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
let dt = match dt_from_ms(ms) {
|
||||
Some(d) => d,
|
||||
None => return Ok(JsValue::float(f64::NAN)),
|
||||
};
|
||||
let nd = dt.with_nanosecond(v as u32 * 1_000_000).unwrap_or(dt);
|
||||
let ts = nd.timestamp_millis() as f64;
|
||||
set_timestamp(obj, ts);
|
||||
Ok(JsValue::float(ts))
|
||||
}
|
||||
|
||||
fn date_to_string_inner(vm: &mut Vm, args: &[u8], format_str: &str, invalid: &str) -> NativeResult {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(vm.intern(invalid));
|
||||
}
|
||||
let s = match dt_from_ms(ms) {
|
||||
Some(dt) => dt.format(format_str).to_string(),
|
||||
None => invalid.to_string(),
|
||||
};
|
||||
Ok(vm.intern(&s))
|
||||
}
|
||||
|
||||
pub fn date_to_iso_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%Y-%m-%dT%H:%M:%S%.3fZ", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_json(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
if !ms.is_finite() {
|
||||
return Ok(JsValue::null());
|
||||
}
|
||||
let s = match dt_from_ms(ms) {
|
||||
Some(dt) => dt.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string(),
|
||||
None => return Ok(JsValue::null()),
|
||||
};
|
||||
Ok(vm.intern(&s))
|
||||
}
|
||||
|
||||
pub fn date_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%a %b %d %Y %H:%M:%S %Z %z", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_date_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%a %b %d %Y", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_time_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%H:%M:%S %Z", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_to_utc_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
date_to_string_inner(vm, args, "%a, %d %b %Y %H:%M:%S GMT", "Invalid Date")
|
||||
}
|
||||
|
||||
pub fn date_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let raw = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
if !raw.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on incompatible receiver",
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*raw.as_js_object_ptr() };
|
||||
ensure_date(vm, obj)?;
|
||||
let ms = get_timestamp(obj);
|
||||
Ok(JsValue::float(ms))
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtins::set::SetKey;
|
||||
use crate::native::NativeResult;
|
||||
use crate::vm::Vm;
|
||||
|
||||
const MAP_PROP_INDEX: u8 = 0;
|
||||
|
||||
fn get_map_inner(
|
||||
vm: &mut Vm,
|
||||
this_val: JsValue,
|
||||
) -> Result<*mut indexmap::IndexMap<SetKey, JsValue>, JsValue> {
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on non-Map object",
|
||||
));
|
||||
}
|
||||
let map_ptr = this_val.as_js_object_ptr();
|
||||
if map_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Map internal state invalid",
|
||||
));
|
||||
}
|
||||
let map_obj = unsafe { &*map_ptr };
|
||||
let inner_val = map_obj.get_prop_at(MAP_PROP_INDEX);
|
||||
if !inner_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Map internal state invalid",
|
||||
));
|
||||
}
|
||||
let inner_ptr = inner_val.as_js_object_ptr() as *mut indexmap::IndexMap<SetKey, JsValue>;
|
||||
if inner_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Map internal state invalid",
|
||||
));
|
||||
}
|
||||
Ok(inner_ptr)
|
||||
}
|
||||
|
||||
fn new_map_inner() -> *mut indexmap::IndexMap<SetKey, JsValue> {
|
||||
Box::into_raw(Box::new(indexmap::IndexMap::new()))
|
||||
}
|
||||
|
||||
fn alloc_map(vm: &mut Vm) -> *mut JsObject {
|
||||
let map_proto = vm.kernel().builtin_world().map_proto.as_ptr() as *mut JsObject;
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(map_proto));
|
||||
let inner = new_map_inner();
|
||||
obj.set_prop_at(MAP_PROP_INDEX, JsValue::object(inner as *mut u8));
|
||||
vm.epoch().alloc(obj)
|
||||
}
|
||||
|
||||
pub fn map_constructor(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
let map_obj = alloc_map(vm);
|
||||
Ok(JsValue::from_js_object(map_obj))
|
||||
}
|
||||
|
||||
pub fn map_set(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_map_inner(vm, this_val)?;
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
let val = vm.reg(if args.len() > 2 { args[2] } else { 0 });
|
||||
unsafe {
|
||||
(*inner).insert(SetKey(key), val);
|
||||
}
|
||||
Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn map_get(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_map_inner(vm, this_val)?;
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
let found = unsafe { (*inner).get(&SetKey(key)).copied() };
|
||||
Ok(found.unwrap_or(JsValue::undefined()))
|
||||
}
|
||||
|
||||
pub fn map_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_map_inner(vm, this_val)?;
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
let found = unsafe { (*inner).contains_key(&SetKey(key)) };
|
||||
Ok(JsValue::bool(found))
|
||||
}
|
||||
|
||||
pub fn map_delete(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_map_inner(vm, this_val)?;
|
||||
let key = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
let removed = unsafe { (*inner).shift_remove(&SetKey(key)) };
|
||||
Ok(JsValue::bool(removed.is_some()))
|
||||
}
|
||||
|
||||
pub fn map_clear(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_map_inner(vm, this_val)?;
|
||||
unsafe {
|
||||
(*inner).clear();
|
||||
}
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn map_size(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_map_inner(vm, this_val)?;
|
||||
Ok(JsValue::float(unsafe { (*inner).len() } as f64))
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
pub mod array;
|
||||
pub mod boolean;
|
||||
pub mod date;
|
||||
pub mod error;
|
||||
pub mod function;
|
||||
pub mod global;
|
||||
pub mod json;
|
||||
pub mod map;
|
||||
pub mod math;
|
||||
pub mod number;
|
||||
pub mod object;
|
||||
pub mod set;
|
||||
pub mod string;
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::native::NativeResult;
|
||||
use crate::vm::Vm;
|
||||
|
||||
const SET_PROP_INDEX: u8 = 0;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SetKey(pub JsValue);
|
||||
|
||||
impl PartialEq for SetKey {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.0.is_double() && other.0.is_double() {
|
||||
let a = self.0.as_double();
|
||||
let b = other.0.as_double();
|
||||
if a.is_nan() && b.is_nan() {
|
||||
return true;
|
||||
}
|
||||
if a == 0.0 && b == 0.0 {
|
||||
return true;
|
||||
}
|
||||
return a == b;
|
||||
}
|
||||
unsafe {
|
||||
std::mem::transmute::<JsValue, u64>(self.0)
|
||||
== std::mem::transmute::<JsValue, u64>(other.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for SetKey {}
|
||||
|
||||
impl Hash for SetKey {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
if self.0.is_double() {
|
||||
let d = self.0.as_double();
|
||||
if d.is_nan() {
|
||||
0u64.hash(state);
|
||||
} else if d == 0.0 {
|
||||
0.0f64.to_bits().hash(state);
|
||||
} else {
|
||||
d.to_bits().hash(state);
|
||||
}
|
||||
} else {
|
||||
unsafe { std::mem::transmute::<JsValue, u64>(self.0).hash(state) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_set_inner(
|
||||
vm: &mut Vm,
|
||||
this_val: JsValue,
|
||||
) -> Result<*mut indexmap::IndexSet<SetKey>, JsValue> {
|
||||
if !this_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"called on non-Set object",
|
||||
));
|
||||
}
|
||||
let set_ptr = this_val.as_js_object_ptr();
|
||||
if set_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Set internal state invalid",
|
||||
));
|
||||
}
|
||||
let set_obj = unsafe { &*set_ptr };
|
||||
let inner_val = set_obj.get_prop_at(SET_PROP_INDEX);
|
||||
if !inner_val.is_object() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Set internal state invalid",
|
||||
));
|
||||
}
|
||||
let inner_ptr = inner_val.as_js_object_ptr() as *mut indexmap::IndexSet<SetKey>;
|
||||
if inner_ptr.is_null() {
|
||||
return Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"Set internal state invalid",
|
||||
));
|
||||
}
|
||||
Ok(inner_ptr)
|
||||
}
|
||||
|
||||
fn new_set_inner() -> *mut indexmap::IndexSet<SetKey> {
|
||||
Box::into_raw(Box::new(indexmap::IndexSet::new()))
|
||||
}
|
||||
|
||||
fn alloc_set(vm: &mut Vm) -> *mut JsObject {
|
||||
let set_proto = vm.kernel().builtin_world().set_proto.as_ptr() as *mut JsObject;
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(set_proto));
|
||||
let inner = new_set_inner();
|
||||
obj.set_prop_at(SET_PROP_INDEX, JsValue::object(inner as *mut u8));
|
||||
vm.epoch().alloc(obj)
|
||||
}
|
||||
|
||||
pub fn set_constructor(vm: &mut Vm, _args: &[u8]) -> NativeResult {
|
||||
let set_obj = alloc_set(vm);
|
||||
Ok(JsValue::from_js_object(set_obj))
|
||||
}
|
||||
|
||||
pub fn set_add(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_set_inner(vm, this_val)?;
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
unsafe {
|
||||
(*inner).insert(SetKey(val));
|
||||
}
|
||||
Ok(this_val)
|
||||
}
|
||||
|
||||
pub fn set_has(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_set_inner(vm, this_val)?;
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
let found = unsafe { (*inner).contains(&SetKey(val)) };
|
||||
Ok(JsValue::bool(found))
|
||||
}
|
||||
|
||||
pub fn set_delete(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_set_inner(vm, this_val)?;
|
||||
let val = vm.reg(if args.len() > 1 { args[1] } else { 0 });
|
||||
let removed = unsafe { (*inner).shift_remove(&SetKey(val)) };
|
||||
Ok(JsValue::bool(removed))
|
||||
}
|
||||
|
||||
pub fn set_clear(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_set_inner(vm, this_val)?;
|
||||
unsafe {
|
||||
(*inner).clear();
|
||||
}
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn set_size(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let inner = get_set_inner(vm, this_val)?;
|
||||
Ok(JsValue::float(unsafe { (*inner).len() } as f64))
|
||||
}
|
||||
@@ -709,6 +709,512 @@ fn bind_json(kernel: &Arc<OxideKernel>, global: &mut JsObject) {
|
||||
global.bump_generation();
|
||||
}
|
||||
|
||||
fn bind_date(kernel: &Arc<OxideKernel>, global: &mut JsObject) {
|
||||
let ctor_ptr = kernel.builtin_world().date_constructor.as_ptr() as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
let proto_ptr = kernel.builtin_world().date_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
let sf = kernel.string_forge().as_ref();
|
||||
let sh = kernel.shape_forge().as_ref();
|
||||
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
ctor,
|
||||
sf,
|
||||
sh,
|
||||
"now",
|
||||
crate::builtins::date::date_now,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
ctor,
|
||||
sf,
|
||||
sh,
|
||||
"parse",
|
||||
crate::builtins::date::date_parse,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
ctor,
|
||||
sf,
|
||||
sh,
|
||||
"UTC",
|
||||
crate::builtins::date::date_utc,
|
||||
7
|
||||
);
|
||||
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getTime",
|
||||
crate::builtins::date::date_get_time,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getFullYear",
|
||||
crate::builtins::date::date_get_full_year,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getMonth",
|
||||
crate::builtins::date::date_get_month,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getDate",
|
||||
crate::builtins::date::date_get_date,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getDay",
|
||||
crate::builtins::date::date_get_day,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getHours",
|
||||
crate::builtins::date::date_get_hours,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getMinutes",
|
||||
crate::builtins::date::date_get_minutes,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getSeconds",
|
||||
crate::builtins::date::date_get_seconds,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getMilliseconds",
|
||||
crate::builtins::date::date_get_milliseconds,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCFullYear",
|
||||
crate::builtins::date::date_get_utc_full_year,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCMonth",
|
||||
crate::builtins::date::date_get_utc_month,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCDate",
|
||||
crate::builtins::date::date_get_utc_date,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCDay",
|
||||
crate::builtins::date::date_get_utc_day,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCHours",
|
||||
crate::builtins::date::date_get_utc_hours,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCMinutes",
|
||||
crate::builtins::date::date_get_utc_minutes,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCSeconds",
|
||||
crate::builtins::date::date_get_utc_seconds,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getUTCMilliseconds",
|
||||
crate::builtins::date::date_get_utc_milliseconds,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"getTimezoneOffset",
|
||||
crate::builtins::date::date_get_timezone_offset,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setTime",
|
||||
crate::builtins::date::date_set_time,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setFullYear",
|
||||
crate::builtins::date::date_set_full_year,
|
||||
3
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setMonth",
|
||||
crate::builtins::date::date_set_month,
|
||||
2
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setDate",
|
||||
crate::builtins::date::date_set_date,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setHours",
|
||||
crate::builtins::date::date_set_hours,
|
||||
4
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setMinutes",
|
||||
crate::builtins::date::date_set_minutes,
|
||||
3
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setSeconds",
|
||||
crate::builtins::date::date_set_seconds,
|
||||
2
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"setMilliseconds",
|
||||
crate::builtins::date::date_set_milliseconds,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"toISOString",
|
||||
crate::builtins::date::date_to_iso_string,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"toJSON",
|
||||
crate::builtins::date::date_to_json,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"toString",
|
||||
crate::builtins::date::date_to_string,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"toDateString",
|
||||
crate::builtins::date::date_to_date_string,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"toTimeString",
|
||||
crate::builtins::date::date_to_time_string,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"toUTCString",
|
||||
crate::builtins::date::date_to_utc_string,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"valueOf",
|
||||
crate::builtins::date::date_value_of,
|
||||
0
|
||||
);
|
||||
|
||||
let si_d = kernel.string_forge().intern("Date").0;
|
||||
let d_shape = kernel.shape_forge().make_shape(global.shape_id(), si_d);
|
||||
let d_val = JsValue::from_js_object(ctor_ptr);
|
||||
global.set_shape_id(d_shape);
|
||||
global.ensure_hash_props().push(Box::new(d_val));
|
||||
global.bump_generation();
|
||||
}
|
||||
|
||||
fn bind_set(kernel: &Arc<OxideKernel>, global: &mut JsObject) {
|
||||
let ctor_ptr = kernel.builtin_world().set_constructor.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = kernel.builtin_world().set_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
let sf = kernel.string_forge().as_ref();
|
||||
let sh = kernel.shape_forge().as_ref();
|
||||
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"add",
|
||||
crate::builtins::set::set_add,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"has",
|
||||
crate::builtins::set::set_has,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"delete",
|
||||
crate::builtins::set::set_delete,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"clear",
|
||||
crate::builtins::set::set_clear,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"size",
|
||||
crate::builtins::set::set_size,
|
||||
0
|
||||
);
|
||||
|
||||
let si_s = kernel.string_forge().intern("Set").0;
|
||||
let s_shape = kernel.shape_forge().make_shape(global.shape_id(), si_s);
|
||||
let s_val = JsValue::from_js_object(ctor_ptr);
|
||||
global.set_shape_id(s_shape);
|
||||
global.ensure_hash_props().push(Box::new(s_val));
|
||||
global.bump_generation();
|
||||
}
|
||||
|
||||
fn bind_map(kernel: &Arc<OxideKernel>, global: &mut JsObject) {
|
||||
let ctor_ptr = kernel.builtin_world().map_constructor.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = kernel.builtin_world().map_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
let sf = kernel.string_forge().as_ref();
|
||||
let sh = kernel.shape_forge().as_ref();
|
||||
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"set",
|
||||
crate::builtins::map::map_set,
|
||||
2
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"get",
|
||||
crate::builtins::map::map_get,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"has",
|
||||
crate::builtins::map::map_has,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"delete",
|
||||
crate::builtins::map::map_delete,
|
||||
1
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"clear",
|
||||
crate::builtins::map::map_clear,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"size",
|
||||
crate::builtins::map::map_size,
|
||||
0
|
||||
);
|
||||
|
||||
let si_m = kernel.string_forge().intern("Map").0;
|
||||
let m_shape = kernel.shape_forge().make_shape(global.shape_id(), si_m);
|
||||
let m_val = JsValue::from_js_object(ctor_ptr);
|
||||
global.set_shape_id(m_shape);
|
||||
global.ensure_hash_props().push(Box::new(m_val));
|
||||
global.bump_generation();
|
||||
}
|
||||
|
||||
fn bind_boolean(kernel: &Arc<OxideKernel>) {
|
||||
let ctor_ptr = kernel.builtin_world().boolean_constructor.as_ptr() as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
let proto_ptr = kernel.builtin_world().boolean_proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
let sf = kernel.string_forge().as_ref();
|
||||
let sh = kernel.shape_forge().as_ref();
|
||||
|
||||
ctor.set_native_fn(Some(
|
||||
crate::builtins::boolean::boolean_constructor as *const (),
|
||||
));
|
||||
ctor.set_native_arg_count(1);
|
||||
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"valueOf",
|
||||
crate::builtins::boolean::boolean_prototype_value_of,
|
||||
0
|
||||
);
|
||||
bind_method!(
|
||||
kernel.builtin_world(),
|
||||
proto,
|
||||
sf,
|
||||
sh,
|
||||
"toString",
|
||||
crate::builtins::boolean::boolean_prototype_to_string,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
fn bind_function(kernel: &Arc<OxideKernel>) {
|
||||
let function_methods = FunctionMethods {
|
||||
call: crate::builtins::function::function_call as *const (),
|
||||
@@ -733,6 +1239,10 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
||||
bind_number(kernel, global);
|
||||
bind_math(kernel, global);
|
||||
bind_json(kernel, global);
|
||||
bind_date(kernel, global);
|
||||
bind_set(kernel, global);
|
||||
bind_map(kernel, global);
|
||||
bind_boolean(kernel);
|
||||
bind_function(kernel);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user