* CWrapper::create_prototype: * @module: Object on which to define the constructor as a property, or the * global object if not given * * Create the class's prototype and store it in the global slot, or retrieve * it if it has already been created. * * Unless DontDefineConstructor is in class_ops.flags, also create the * class's constructor, and define it
| 398 | * class's constructor, and define it as a property on @module. |
| 399 | */ |
| 400 | GJS_JSAPI_RETURN_CONVENTION |
| 401 | static JSObject* create_prototype(JSContext* cx, |
| 402 | JS::HandleObject module = nullptr) { |
| 403 | JSObject* global = JS::CurrentGlobalOrNull(cx); |
| 404 | assert(global && "Must be in a realm to call create_prototype()"); |
| 405 | |
| 406 | // If we've been here more than once, we already have the proto |
| 407 | JS::RootedValue v_proto( |
| 408 | cx, gjs_get_global_slot(global, Base::PROTOTYPE_SLOT)); |
| 409 | if (!v_proto.isUndefined()) { |
| 410 | assert(v_proto.isObject() && |
| 411 | "Someone stored some weird value in a global slot"); |
| 412 | return &v_proto.toObject(); |
| 413 | } |
| 414 | |
| 415 | // Workaround for ubsan bug |
| 416 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71962 |
| 417 | // Note that the corresponding function pointers in the js::ClassSpec |
| 418 | // must be initialized as nullptr, not the default initializer! (see |
| 419 | // e.g. CairoPath::class_spec.finishInit) |
| 420 | using NullOpType = |
| 421 | std::integral_constant<js::ClassObjectCreationOp, nullptr>; |
| 422 | using CreateConstructorType = |
| 423 | std::integral_constant<js::ClassObjectCreationOp, |
| 424 | Base::klass.spec->createConstructor>; |
| 425 | using CreatePrototypeType = |
| 426 | std::integral_constant<js::ClassObjectCreationOp, |
| 427 | Base::klass.spec->createPrototype>; |
| 428 | using NullFuncsType = |
| 429 | std::integral_constant<const JSFunctionSpec*, nullptr>; |
| 430 | using ConstructorFuncsType = |
| 431 | std::integral_constant<const JSFunctionSpec*, |
| 432 | Base::klass.spec->constructorFunctions>; |
| 433 | using PrototypeFuncsType = |
| 434 | std::integral_constant<const JSFunctionSpec*, |
| 435 | Base::klass.spec->prototypeFunctions>; |
| 436 | using NullPropsType = |
| 437 | std::integral_constant<const JSPropertySpec*, nullptr>; |
| 438 | using ConstructorPropsType = |
| 439 | std::integral_constant<const JSPropertySpec*, |
| 440 | Base::klass.spec->constructorProperties>; |
| 441 | using PrototypePropsType = |
| 442 | std::integral_constant<const JSPropertySpec*, |
| 443 | Base::klass.spec->prototypeProperties>; |
| 444 | using NullFinishOpType = |
| 445 | std::integral_constant<js::FinishClassInitOp, nullptr>; |
| 446 | using FinishInitType = |
| 447 | std::integral_constant<js::FinishClassInitOp, |
| 448 | Base::klass.spec->finishInit>; |
| 449 | |
| 450 | // Create the prototype. If no createPrototype function is provided, |
| 451 | // then the default is to create a plain object as the prototype. |
| 452 | JS::RootedObject proto(cx); |
| 453 | if constexpr (!std::is_same_v<CreatePrototypeType, NullOpType>) { |
| 454 | proto = Base::klass.spec->createPrototype(cx, JSProto_Object); |
| 455 | } else { |
| 456 | proto = JS_NewPlainObject(cx); |
| 457 | } |
nothing calls this directly
no test coverage detected