1use crate::host::{with_host, JsObj};
23use fusevm::Value;
24
25pub const METHODS: &[&str] = &[
26 "isDate",
27 "isRegExp",
28 "isMap",
29 "isSet",
30 "isWeakMap",
31 "isWeakSet",
32 "isPromise",
33 "isArrayBuffer",
34 "isSharedArrayBuffer",
35 "isAnyArrayBuffer",
36 "isTypedArray",
37 "isDataView",
38 "isUint8Array",
39 "isUint8ClampedArray",
40 "isUint16Array",
41 "isUint32Array",
42 "isInt8Array",
43 "isInt16Array",
44 "isInt32Array",
45 "isFloat32Array",
46 "isFloat64Array",
47 "isBigInt64Array",
48 "isBigUint64Array",
49 "isAsyncFunction",
50 "isGeneratorFunction",
51 "isGeneratorObject",
52 "isProxy",
53 "isNativeError",
54 "isBoxedPrimitive",
55 "isArgumentsObject",
56 "isNumberObject",
57 "isStringObject",
58 "isBooleanObject",
59 "isSymbolObject",
60 "isBigIntObject",
61 "isModuleNamespaceObject",
62 "isExternal",
63 "isArrayBufferView",
64 "isCryptoKey",
65 "isKeyObject",
66 "isFloat16Array",
67 "isMapIterator",
68 "isSetIterator",
69];
70
71pub fn call(method: &str, args: &[Value]) -> Option<Result<Value, String>> {
72 let v = args.first().cloned().unwrap_or(Value::Undef);
73 let b = |x: bool| Some(Ok(Value::Bool(x)));
74 match method {
75 "isDate" => b(super::native_tag(&v).as_deref() == Some("Date")),
76 "isRegExp" => b(with_host(|h| matches!(h.get(&v), Some(JsObj::RegExp(_))))),
77 "isMap" => b(with_host(|h| {
78 matches!(h.get(&v), Some(JsObj::Map { weak: false, .. }))
79 })),
80 "isSet" => b(with_host(|h| {
81 matches!(h.get(&v), Some(JsObj::Set { weak: false, .. }))
82 })),
83 "isWeakMap" => b(with_host(|h| {
84 matches!(h.get(&v), Some(JsObj::Map { weak: true, .. }))
85 })),
86 "isWeakSet" => b(with_host(|h| {
87 matches!(h.get(&v), Some(JsObj::Set { weak: true, .. }))
88 })),
89 "isPromise" => b(with_host(|h| {
90 matches!(h.get(&v), Some(JsObj::Promise { .. }))
91 })),
92
93 "isArrayBuffer" => b(super::native_tag(&v).as_deref() == Some("ArrayBuffer")),
96 "isSharedArrayBuffer" => b(false),
97 "isAnyArrayBuffer" => b(super::native_tag(&v).as_deref() == Some("ArrayBuffer")),
98 "isDataView" => b(super::native_tag(&v).as_deref() == Some("DataView")),
99
100 "isTypedArray" => b(ta_kind(&v).is_some()),
104 "isUint8Array" => b(ta_kind(&v).as_deref() == Some("Uint8Array")),
105 "isUint8ClampedArray" => b(ta_kind(&v).as_deref() == Some("Uint8ClampedArray")),
106 "isUint16Array" => b(ta_kind(&v).as_deref() == Some("Uint16Array")),
107 "isUint32Array" => b(ta_kind(&v).as_deref() == Some("Uint32Array")),
108 "isInt8Array" => b(ta_kind(&v).as_deref() == Some("Int8Array")),
109 "isInt16Array" => b(ta_kind(&v).as_deref() == Some("Int16Array")),
110 "isInt32Array" => b(ta_kind(&v).as_deref() == Some("Int32Array")),
111 "isFloat32Array" => b(ta_kind(&v).as_deref() == Some("Float32Array")),
112 "isFloat64Array" => b(ta_kind(&v).as_deref() == Some("Float64Array")),
113 "isBigInt64Array" => b(ta_kind(&v).as_deref() == Some("BigInt64Array")),
114 "isBigUint64Array" => b(ta_kind(&v).as_deref() == Some("BigUint64Array")),
115
116 "isAsyncFunction" => b(func_flag(&v, FuncFlag::Async)),
117 "isGeneratorFunction" => b(func_flag(&v, FuncFlag::Generator)),
118 "isGeneratorObject" => b(with_host(|h| {
119 matches!(h.get(&v), Some(JsObj::Generator { .. }))
120 })),
121
122 "isProxy" => b(with_host(|h| h.kind_of(&v)) == Some(crate::host::ObjKind::Proxy)),
123 "isNativeError" => b(is_native_error(&v)),
126
127 "isBoxedPrimitive" => b(boxed_kind(&v).is_some()),
129 "isNumberObject" => b(boxed_kind(&v) == Some(Boxed::Number)),
130 "isStringObject" => b(boxed_kind(&v) == Some(Boxed::String)),
131 "isBooleanObject" => b(boxed_kind(&v) == Some(Boxed::Boolean)),
132 "isSymbolObject" => b(boxed_kind(&v) == Some(Boxed::Symbol)),
133 "isBigIntObject" => b(boxed_kind(&v) == Some(Boxed::BigInt)),
134
135 "isArgumentsObject" => b(crate::builtins::is_arguments(&v)),
137 "isModuleNamespaceObject" | "isExternal" => b(false),
138
139 "isArrayBufferView" => {
142 b(ta_kind(&v).is_some() || super::native_tag(&v).as_deref() == Some("DataView"))
143 }
144 "isFloat16Array" => b(ta_kind(&v).as_deref() == Some("Float16Array")),
146 "isCryptoKey" | "isKeyObject" => b(false),
148 "isMapIterator" | "isSetIterator" => b(false),
153
154 _ => None,
155 }
156}
157
158#[derive(PartialEq, Eq, Clone, Copy)]
160enum Boxed {
161 Number,
162 String,
163 Boolean,
164 Symbol,
165 BigInt,
166}
167
168fn boxed_kind(v: &Value) -> Option<Boxed> {
173 let prim = crate::builtins::wrapped_primitive(v)?;
174 Some(with_host(|h| match h.get(&prim) {
175 Some(JsObj::Str(_)) => Boxed::String,
176 Some(JsObj::Symbol { .. }) => Boxed::Symbol,
177 Some(JsObj::BigInt(_)) => Boxed::BigInt,
178 _ => match prim {
179 Value::Bool(_) => Boxed::Boolean,
180 _ => Boxed::Number,
181 },
182 }))
183}
184
185fn ta_kind(v: &Value) -> Option<String> {
189 match super::native_tag(v).as_deref() {
190 Some("TypedArray") => with_host(|h| match h.get(v) {
191 Some(JsObj::Object(p)) => p.get("@@kind").map(|k| h.str_of(k)),
192 _ => None,
193 }),
194 Some("Buffer") => Some("Uint8Array".to_string()),
195 _ => None,
196 }
197}
198
199enum FuncFlag {
201 Async,
202 Generator,
203}
204
205fn func_flag(v: &Value, flag: FuncFlag) -> bool {
209 let def_id = with_host(|h| match h.get(v) {
210 Some(JsObj::Func(f)) => Some(f.def_id),
211 _ => None,
212 });
213 with_host(|h| {
214 def_id
215 .and_then(|id| h.funcs.get(id))
216 .map(|d| match flag {
217 FuncFlag::Async => d.is_async,
218 FuncFlag::Generator => d.is_generator,
219 })
220 .unwrap_or(false)
221 })
222}
223
224fn is_native_error(v: &Value) -> bool {
227 if !matches!(v, Value::Obj(_)) {
228 return false;
229 }
230 let err_ctor = with_host(|h| h.alloc(JsObj::Builtin("Error".into())));
231 crate::host::instance_of(v, &err_ctor).unwrap_or(false)
232}