1use crate::host::{with_host, JsObj};
26use fusevm::Value;
27
28pub const METHODS: &[&str] = &[
29 "isDate",
30 "isRegExp",
31 "isMap",
32 "isSet",
33 "isWeakMap",
34 "isWeakSet",
35 "isPromise",
36 "isArrayBuffer",
37 "isSharedArrayBuffer",
38 "isAnyArrayBuffer",
39 "isTypedArray",
40 "isDataView",
41 "isUint8Array",
42 "isUint8ClampedArray",
43 "isUint16Array",
44 "isUint32Array",
45 "isInt8Array",
46 "isInt16Array",
47 "isInt32Array",
48 "isFloat32Array",
49 "isFloat64Array",
50 "isBigInt64Array",
51 "isBigUint64Array",
52 "isAsyncFunction",
53 "isGeneratorFunction",
54 "isGeneratorObject",
55 "isProxy",
56 "isNativeError",
57 "isBoxedPrimitive",
58 "isArgumentsObject",
59 "isNumberObject",
60 "isStringObject",
61 "isBooleanObject",
62 "isSymbolObject",
63 "isBigIntObject",
64 "isModuleNamespaceObject",
65 "isExternal",
66 "isArrayBufferView",
67 "isCryptoKey",
68 "isKeyObject",
69 "isFloat16Array",
70 "isMapIterator",
71 "isSetIterator",
72];
73
74pub fn call(method: &str, args: &[Value]) -> Option<Result<Value, String>> {
75 let v = args.first().cloned().unwrap_or(Value::Undef);
76 let b = |x: bool| Some(Ok(Value::Bool(x)));
77 match method {
78 "isDate" => b(super::native_tag(&v).as_deref() == Some("Date")),
79 "isRegExp" => b(with_host(|h| matches!(h.get(&v), Some(JsObj::RegExp(_))))),
80 "isMap" => b(with_host(|h| {
81 matches!(h.get(&v), Some(JsObj::Map { weak: false, .. }))
82 })),
83 "isSet" => b(with_host(|h| {
84 matches!(h.get(&v), Some(JsObj::Set { weak: false, .. }))
85 })),
86 "isWeakMap" => b(with_host(|h| {
87 matches!(h.get(&v), Some(JsObj::Map { weak: true, .. }))
88 })),
89 "isWeakSet" => b(with_host(|h| {
90 matches!(h.get(&v), Some(JsObj::Set { weak: true, .. }))
91 })),
92 "isPromise" => b(with_host(|h| {
93 matches!(h.get(&v), Some(JsObj::Promise { .. }))
94 })),
95
96 "isArrayBuffer" => b(super::native_tag(&v).as_deref() == Some("ArrayBuffer")),
99 "isSharedArrayBuffer" => b(false),
100 "isAnyArrayBuffer" => b(super::native_tag(&v).as_deref() == Some("ArrayBuffer")),
101 "isDataView" => b(false),
102
103 "isTypedArray" => b(ta_kind(&v).is_some()),
107 "isUint8Array" => b(ta_kind(&v).as_deref() == Some("Uint8Array")),
108 "isUint8ClampedArray" => b(ta_kind(&v).as_deref() == Some("Uint8ClampedArray")),
109 "isUint16Array" => b(ta_kind(&v).as_deref() == Some("Uint16Array")),
110 "isUint32Array" => b(ta_kind(&v).as_deref() == Some("Uint32Array")),
111 "isInt8Array" => b(ta_kind(&v).as_deref() == Some("Int8Array")),
112 "isInt16Array" => b(ta_kind(&v).as_deref() == Some("Int16Array")),
113 "isInt32Array" => b(ta_kind(&v).as_deref() == Some("Int32Array")),
114 "isFloat32Array" => b(ta_kind(&v).as_deref() == Some("Float32Array")),
115 "isFloat64Array" => b(ta_kind(&v).as_deref() == Some("Float64Array")),
116 "isBigInt64Array" => b(false),
118 "isBigUint64Array" => b(false),
119
120 "isAsyncFunction" => b(func_flag(&v, FuncFlag::Async)),
121 "isGeneratorFunction" => b(func_flag(&v, FuncFlag::Generator)),
122 "isGeneratorObject" => b(with_host(|h| {
123 matches!(h.get(&v), Some(JsObj::Generator { .. }))
124 })),
125
126 "isProxy" => b(false),
128 "isNativeError" => b(is_native_error(&v)),
131
132 "isBoxedPrimitive" | "isNumberObject" | "isStringObject" | "isBooleanObject"
135 | "isSymbolObject" | "isBigIntObject" => b(false),
136
137 "isArgumentsObject" | "isModuleNamespaceObject" | "isExternal" => b(false),
140
141 "isArrayBufferView" => b(ta_kind(&v).is_some()),
145 "isFloat16Array" => b(ta_kind(&v).as_deref() == Some("Float16Array")),
147 "isCryptoKey" | "isKeyObject" => b(false),
149 "isMapIterator" | "isSetIterator" => b(false),
154
155 _ => None,
156 }
157}
158
159fn ta_kind(v: &Value) -> Option<String> {
163 match super::native_tag(v).as_deref() {
164 Some("TypedArray") => with_host(|h| match h.get(v) {
165 Some(JsObj::Object(p)) => p.get("@@kind").map(|k| h.str_of(k)),
166 _ => None,
167 }),
168 Some("Buffer") => Some("Uint8Array".to_string()),
169 _ => None,
170 }
171}
172
173enum FuncFlag {
175 Async,
176 Generator,
177}
178
179fn func_flag(v: &Value, flag: FuncFlag) -> bool {
183 let def_id = with_host(|h| match h.get(v) {
184 Some(JsObj::Func(f)) => Some(f.def_id),
185 _ => None,
186 });
187 with_host(|h| {
188 def_id
189 .and_then(|id| h.funcs.get(id))
190 .map(|d| match flag {
191 FuncFlag::Async => d.is_async,
192 FuncFlag::Generator => d.is_generator,
193 })
194 .unwrap_or(false)
195 })
196}
197
198fn is_native_error(v: &Value) -> bool {
201 if !matches!(v, Value::Obj(_)) {
202 return false;
203 }
204 let err_ctor = with_host(|h| h.alloc(JsObj::Builtin("Error".into())));
205 crate::host::instance_of(v, &err_ctor).unwrap_or(false)
206}