use crate::host::{with_host, JsObj};
use fusevm::Value;
pub const METHODS: &[&str] = &[
"isDate",
"isRegExp",
"isMap",
"isSet",
"isWeakMap",
"isWeakSet",
"isPromise",
"isArrayBuffer",
"isSharedArrayBuffer",
"isAnyArrayBuffer",
"isTypedArray",
"isDataView",
"isUint8Array",
"isUint8ClampedArray",
"isUint16Array",
"isUint32Array",
"isInt8Array",
"isInt16Array",
"isInt32Array",
"isFloat32Array",
"isFloat64Array",
"isBigInt64Array",
"isBigUint64Array",
"isAsyncFunction",
"isGeneratorFunction",
"isGeneratorObject",
"isProxy",
"isNativeError",
"isBoxedPrimitive",
"isArgumentsObject",
"isNumberObject",
"isStringObject",
"isBooleanObject",
"isSymbolObject",
"isBigIntObject",
"isModuleNamespaceObject",
"isExternal",
"isArrayBufferView",
"isCryptoKey",
"isKeyObject",
"isFloat16Array",
"isMapIterator",
"isSetIterator",
];
pub fn call(method: &str, args: &[Value]) -> Option<Result<Value, String>> {
let v = args.first().cloned().unwrap_or(Value::Undef);
let b = |x: bool| Some(Ok(Value::Bool(x)));
match method {
"isDate" => b(super::native_tag(&v).as_deref() == Some("Date")),
"isRegExp" => b(with_host(|h| matches!(h.get(&v), Some(JsObj::RegExp(_))))),
"isMap" => b(with_host(|h| {
matches!(h.get(&v), Some(JsObj::Map { weak: false, .. }))
})),
"isSet" => b(with_host(|h| {
matches!(h.get(&v), Some(JsObj::Set { weak: false, .. }))
})),
"isWeakMap" => b(with_host(|h| {
matches!(h.get(&v), Some(JsObj::Map { weak: true, .. }))
})),
"isWeakSet" => b(with_host(|h| {
matches!(h.get(&v), Some(JsObj::Set { weak: true, .. }))
})),
"isPromise" => b(with_host(|h| {
matches!(h.get(&v), Some(JsObj::Promise { .. }))
})),
"isArrayBuffer" => b(super::native_tag(&v).as_deref() == Some("ArrayBuffer")),
"isSharedArrayBuffer" => b(false),
"isAnyArrayBuffer" => b(super::native_tag(&v).as_deref() == Some("ArrayBuffer")),
"isDataView" => b(false),
"isTypedArray" => b(ta_kind(&v).is_some()),
"isUint8Array" => b(ta_kind(&v).as_deref() == Some("Uint8Array")),
"isUint8ClampedArray" => b(ta_kind(&v).as_deref() == Some("Uint8ClampedArray")),
"isUint16Array" => b(ta_kind(&v).as_deref() == Some("Uint16Array")),
"isUint32Array" => b(ta_kind(&v).as_deref() == Some("Uint32Array")),
"isInt8Array" => b(ta_kind(&v).as_deref() == Some("Int8Array")),
"isInt16Array" => b(ta_kind(&v).as_deref() == Some("Int16Array")),
"isInt32Array" => b(ta_kind(&v).as_deref() == Some("Int32Array")),
"isFloat32Array" => b(ta_kind(&v).as_deref() == Some("Float32Array")),
"isFloat64Array" => b(ta_kind(&v).as_deref() == Some("Float64Array")),
"isBigInt64Array" => b(false),
"isBigUint64Array" => b(false),
"isAsyncFunction" => b(func_flag(&v, FuncFlag::Async)),
"isGeneratorFunction" => b(func_flag(&v, FuncFlag::Generator)),
"isGeneratorObject" => b(with_host(|h| {
matches!(h.get(&v), Some(JsObj::Generator { .. }))
})),
"isProxy" => b(false),
"isNativeError" => b(is_native_error(&v)),
"isBoxedPrimitive" | "isNumberObject" | "isStringObject" | "isBooleanObject"
| "isSymbolObject" | "isBigIntObject" => b(false),
"isArgumentsObject" | "isModuleNamespaceObject" | "isExternal" => b(false),
"isArrayBufferView" => b(ta_kind(&v).is_some()),
"isFloat16Array" => b(ta_kind(&v).as_deref() == Some("Float16Array")),
"isCryptoKey" | "isKeyObject" => b(false),
"isMapIterator" | "isSetIterator" => b(false),
_ => None,
}
}
fn ta_kind(v: &Value) -> Option<String> {
match super::native_tag(v).as_deref() {
Some("TypedArray") => with_host(|h| match h.get(v) {
Some(JsObj::Object(p)) => p.get("@@kind").map(|k| h.str_of(k)),
_ => None,
}),
Some("Buffer") => Some("Uint8Array".to_string()),
_ => None,
}
}
enum FuncFlag {
Async,
Generator,
}
fn func_flag(v: &Value, flag: FuncFlag) -> bool {
let def_id = with_host(|h| match h.get(v) {
Some(JsObj::Func(f)) => Some(f.def_id),
_ => None,
});
with_host(|h| {
def_id
.and_then(|id| h.funcs.get(id))
.map(|d| match flag {
FuncFlag::Async => d.is_async,
FuncFlag::Generator => d.is_generator,
})
.unwrap_or(false)
})
}
fn is_native_error(v: &Value) -> bool {
if !matches!(v, Value::Obj(_)) {
return false;
}
let err_ctor = with_host(|h| h.alloc(JsObj::Builtin("Error".into())));
crate::host::instance_of(v, &err_ctor).unwrap_or(false)
}