PrototypeObject.h 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /*
  2. * Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/StringView.h>
  8. #include <AK/TypeCasts.h>
  9. #include <LibJS/Runtime/Completion.h>
  10. #include <LibJS/Runtime/GlobalObject.h>
  11. #include <LibJS/Runtime/Object.h>
  12. namespace JS {
  13. #define JS_PROTOTYPE_OBJECT(prototype_class, object_class, display_name_) \
  14. using Prototype = PrototypeObject<prototype_class, object_class>; \
  15. JS_OBJECT(prototype_class, Prototype) \
  16. static constexpr StringView display_name() \
  17. { \
  18. return #display_name_##sv; \
  19. }
  20. template<typename PrototypeType, typename ObjectType>
  21. class PrototypeObject : public Object {
  22. JS_OBJECT(PrototypeObject, Object);
  23. public:
  24. virtual ~PrototypeObject() override = default;
  25. static ThrowCompletionOr<GC::Ref<Object>> this_object(VM& vm)
  26. {
  27. auto this_value = vm.this_value();
  28. if (!this_value.is_object())
  29. return vm.throw_completion<TypeError>(ErrorType::NotAnObject, this_value);
  30. return this_value.as_object();
  31. }
  32. // Use typed_this_object() when the spec coerces |this| value to an object.
  33. static ThrowCompletionOr<GC::Ref<ObjectType>> typed_this_object(VM& vm)
  34. {
  35. auto this_object = TRY(vm.this_value().to_object(vm));
  36. if (!is<ObjectType>(*this_object))
  37. return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, PrototypeType::display_name());
  38. return static_cast<ObjectType&>(*this_object);
  39. }
  40. // Use typed_this_value() when the spec does not coerce |this| value to an object.
  41. static ThrowCompletionOr<GC::Ref<ObjectType>> typed_this_value(VM& vm)
  42. {
  43. auto this_value = vm.this_value();
  44. if (!this_value.is_object() || !is<ObjectType>(this_value.as_object()))
  45. return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, PrototypeType::display_name());
  46. return static_cast<ObjectType&>(this_value.as_object());
  47. }
  48. protected:
  49. explicit PrototypeObject(Object& prototype)
  50. : Object(ConstructWithPrototypeTag::Tag, prototype)
  51. {
  52. }
  53. };
  54. }