| 335 | // See GIWrapperBase::constructor(). |
| 336 | template <class Base, class Prototype, class Instance> |
| 337 | bool BoxedInstance<Base, Prototype, Instance>::constructor_impl( |
| 338 | JSContext* cx, JS::HandleObject obj, const JS::CallArgs& args) { |
| 339 | // Short-circuit copy-construction in the case where we can use copy_boxed() |
| 340 | // or copy_memory() |
| 341 | Base* source_priv; |
| 342 | if (args.length() == 1 && (source_priv = get_copy_source(cx, args[0]))) { |
| 343 | if (!source_priv->check_is_instance(cx, "construct boxed object")) |
| 344 | return false; |
| 345 | |
| 346 | if (g_type_is_a(gtype(), G_TYPE_BOXED)) { |
| 347 | copy_boxed(source_priv->to_instance()); |
| 348 | return true; |
| 349 | } |
| 350 | if (get_prototype()->can_allocate_directly()) { |
| 351 | copy_memory(source_priv->to_instance()); |
| 352 | return true; |
| 353 | } |
| 354 | } |
| 355 | |
| 356 | Prototype* proto = get_prototype(); |
| 357 | |
| 358 | // If the structure is registered as a boxed, we can create a new instance |
| 359 | // by looking for a zero-args constructor and calling it. Constructors don't |
| 360 | // really make sense for non-boxed types, since there is no memory |
| 361 | // management for the return value, and m_zero_args_constructor and |
| 362 | // m_default_constructor are always Nothing for them. |
| 363 | // |
| 364 | // For backward compatibility, we choose the zero args constructor if one |
| 365 | // exists, otherwise we malloc the correct amount of space if possible; |
| 366 | // finally, we fallback on the default constructor. |
| 367 | if (Maybe<GI::AutoFunctionInfo> zero_args_info{ |
| 368 | proto->zero_args_constructor_info()}; |
| 369 | zero_args_info) { |
| 370 | GIArgument rval_arg; |
| 371 | Gjs::GErrorResult<> result = zero_args_info->invoke({}, {}, &rval_arg); |
| 372 | if (result.isErr()) { |
| 373 | gjs_throw(cx, "Failed to invoke boxed constructor: %s", |
| 374 | result.inspectErr()->message); |
| 375 | return false; |
| 376 | } |
| 377 | |
| 378 | own_ptr(gjs_arg_steal<void*>(&rval_arg)); |
| 379 | |
| 380 | debug_lifecycle("Boxed pointer created from zero-args constructor"); |
| 381 | |
| 382 | } else if (Maybe<GI::AutoFunctionInfo> default_ctor_info{ |
| 383 | proto->default_constructor_info()}; |
| 384 | proto->can_allocate_directly_without_pointers() || |
| 385 | (!default_ctor_info && proto->can_allocate_directly())) { |
| 386 | // has_default_constructor() takes priority over can_allocate_directly() |
| 387 | // for historical compatibility reasons |
| 388 | allocate_directly(); |
| 389 | } else if (default_ctor_info) { |
| 390 | js::ESClass es_class = js::ESClass::Other; |
| 391 | if (proto->can_allocate_directly() && args.length() == 1 && |
| 392 | args[0].isObject()) { |
| 393 | JS::RootedObject arg0{cx, &args[0].toObject()}; |
| 394 | if (!JS::GetBuiltinClass(cx, arg0, &es_class)) |
no test coverage detected