| 521 | template <class Base, class Prototype, class Instance> |
| 522 | template <class FieldInstance> |
| 523 | bool BoxedInstance<Base, Prototype, Instance>::get_nested_interface_object( |
| 524 | JSContext* cx, JSObject* parent_obj, const GI::FieldInfo& field_info, |
| 525 | const GI::UnownedInfo<FieldInstance::TAG>& struct_info, |
| 526 | JS::MutableHandleValue value) const { |
| 527 | if (!GI::struct_is_simple(struct_info)) { |
| 528 | gjs_throw(cx, "Reading field %s.%s is not supported", |
| 529 | format_name().c_str(), field_info.name()); |
| 530 | |
| 531 | return false; |
| 532 | } |
| 533 | |
| 534 | // If we have already set the field from a JS object which we have stashed |
| 535 | // because it owns pointers, return that JS object instead of creating one. |
| 536 | auto entry = m_nested_objects.lookup(field_info.name()); |
| 537 | if (entry.found()) { |
| 538 | value.setObject(*entry->value().get()); |
| 539 | return true; |
| 540 | } |
| 541 | |
| 542 | JS::RootedObject obj{ |
| 543 | cx, gjs_new_object_with_generic_prototype(cx, struct_info)}; |
| 544 | if (!obj) |
| 545 | return false; |
| 546 | |
| 547 | FieldInstance* priv = FieldInstance::new_for_js_object(cx, obj); |
| 548 | |
| 549 | // A structure nested inside a parent object; doesn't have an independent |
| 550 | // allocation |
| 551 | adopt_nested_ptr(priv, raw_ptr() + field_info.offset()); |
| 552 | |
| 553 | /* We never actually read the reserved slot, but we put the parent object |
| 554 | * into it to hold onto the parent object. |
| 555 | */ |
| 556 | JS::SetReservedSlot(obj, BoxedInstance::PARENT_OBJECT, |
| 557 | JS::ObjectValue(*parent_obj)); |
| 558 | |
| 559 | value.setObject(*obj); |
| 560 | return true; |
| 561 | } |
| 562 | |
| 563 | /** |
| 564 | * BoxedBase::field_getter: |
nothing calls this directly
no test coverage detected