Skip to main content

boa_engine/builtins/
is_html_dda.rs

1//! Implementation of the `[[IsHTMLDDA]]` internal slot.
2//!
3//! Objects with this internal slot have special behavior:
4//! - `typeof` returns `"undefined"`
5//! - `ToBoolean` returns `false`
6//! - Abstract equality with `null` or `undefined` returns `true`
7//!
8//! More information:
9//!  - [ECMAScript reference][spec]
10//!
11//! [spec]: https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
12
13use boa_gc::{Finalize, Trace};
14
15use crate::{
16    JsResult, JsValue,
17    object::{
18        JsData, JsObject,
19        internal_methods::{
20            CallValue, InternalMethodCallContext, InternalObjectMethods, ORDINARY_INTERNAL_METHODS,
21        },
22    },
23};
24
25/// Marker struct for objects with the `[[IsHTMLDDA]]` internal slot.
26///
27/// This is used by the `$262.IsHTMLDDA` test harness object and models the
28/// legacy `document.all` behavior per ECMAScript Annex B §B.3.6.
29///
30/// The object is callable — when called, it returns `undefined`.
31#[derive(Debug, Clone, Copy, Trace, Finalize)]
32#[boa_gc(empty_trace)]
33pub struct IsHTMLDDA;
34
35impl JsData for IsHTMLDDA {
36    fn internal_methods(&self) -> &'static InternalObjectMethods {
37        static IS_HTML_DDA_INTERNAL_METHODS: InternalObjectMethods = InternalObjectMethods {
38            __call__: is_html_dda_call,
39            ..ORDINARY_INTERNAL_METHODS
40        };
41        &IS_HTML_DDA_INTERNAL_METHODS
42    }
43}
44
45/// The `[[Call]]` internal method for `IsHTMLDDA` objects.
46///
47/// When called, simply returns `undefined`.
48#[allow(clippy::unnecessary_wraps)]
49fn is_html_dda_call(
50    _obj: &JsObject,
51    argument_count: usize,
52    context: &mut InternalMethodCallContext<'_>,
53) -> JsResult<CallValue> {
54    // Pop the arguments, function, and this from the stack.
55    let _args = context
56        .vm
57        .stack
58        .calling_convention_pop_arguments(argument_count);
59    let _func = context.vm.stack.pop();
60    let _this = context.vm.stack.pop();
61
62    // Push undefined as the return value.
63    context.vm.stack.push(JsValue::undefined());
64
65    Ok(CallValue::Complete)
66}