Skip to main content

nanvm_lib/vm/any/
typeof_.rs

1use crate::vm::{
2    Any, Array, BigInt, Function, IVm, Number, Object, String, dispatch::Dispatch, nullish::Nullish,
3};
4
5/// The tag `Any::typeof_` returns, one per `Unpacked` variant.
6struct TypeOf;
7
8impl<A: IVm> Dispatch<A> for TypeOf {
9    type Result = &'static str;
10
11    fn nullish(self, v: Nullish) -> Self::Result {
12        match v {
13            // `null` is famously an object in JavaScript's `typeof`.
14            Nullish::Null => "object",
15            Nullish::Undefined => "undefined",
16        }
17    }
18
19    fn bool(self, _: bool) -> Self::Result {
20        "boolean"
21    }
22
23    fn number(self, _: Number) -> Self::Result {
24        "number"
25    }
26
27    fn string(self, _: String<A>) -> Self::Result {
28        "string"
29    }
30
31    fn bigint(self, _: BigInt<A>) -> Self::Result {
32        "bigint"
33    }
34
35    fn object(self, _: Object<A>) -> Self::Result {
36        "object"
37    }
38
39    fn array(self, _: Array<A>) -> Self::Result {
40        "object"
41    }
42
43    fn function(self, _: Function<A>) -> Self::Result {
44        "function"
45    }
46}
47
48impl<A: IVm> Any<A> {
49    /// `typeof`. Not a `core::ops` trait — Rust has no unary operator to
50    /// spell it with — so this is a plain method, the same as `unary_plus`.
51    /// Named `typeof_`, not `type_of`: `typeof` is itself a reserved word, and
52    /// a trailing underscore — the convention FJS and JS both use for this —
53    /// resolves the collision while keeping the name recognizable. Never
54    /// throws, but stays a `Result` to match every other operator's shape.
55    /// <https://tc39.es/ecma262/#sec-typeof-operator>
56    pub fn typeof_(self) -> Result<Any<A>, Any<A>> {
57        Ok(self.dispatch(TypeOf).into())
58    }
59}