| 40 | }; |
| 41 | |
| 42 | bool gjs_init_class_dynamic(JSContext* cx, JS::HandleObject in_object, |
| 43 | JS::HandleObject parent_proto, const char* ns_name, |
| 44 | const char* class_name, const JSClass* clasp, |
| 45 | JSNative constructor_native, unsigned nargs, |
| 46 | JSPropertySpec* proto_ps, JSFunctionSpec* proto_fs, |
| 47 | JSPropertySpec* static_ps, |
| 48 | JSFunctionSpec* static_fs, |
| 49 | JS::MutableHandleObject prototype, |
| 50 | JS::MutableHandleObject constructor) { |
| 51 | // Without a name, JS_NewObject() fails |
| 52 | g_assert(clasp->name != nullptr); |
| 53 | |
| 54 | // gjs_init_class_dynamic only makes sense for instantiable classes, use |
| 55 | // JS_InitClass for static classes like Math |
| 56 | g_assert(constructor_native != nullptr); |
| 57 | |
| 58 | // Class initialization consists of five parts: |
| 59 | // - building a prototype |
| 60 | // - defining prototype properties and functions |
| 61 | // - building a constructor and defining it on the right object |
| 62 | // - defining constructor properties and functions |
| 63 | // - linking the constructor and the prototype, so that |
| 64 | // JS_NewObjectForConstructor() can find it |
| 65 | |
| 66 | if (parent_proto) { |
| 67 | prototype.set(JS_NewObjectWithGivenProto(cx, clasp, parent_proto)); |
| 68 | } else { |
| 69 | /* JS_NewObject will use Object.prototype as the prototype if the |
| 70 | * clasp's constructor is not a built-in class. |
| 71 | */ |
| 72 | prototype.set(JS_NewObject(cx, clasp)); |
| 73 | } |
| 74 | if (!prototype) |
| 75 | return false; |
| 76 | |
| 77 | if (proto_ps && !JS_DefineProperties(cx, prototype, proto_ps)) |
| 78 | return false; |
| 79 | if (proto_fs && !JS_DefineFunctions(cx, prototype, proto_fs)) |
| 80 | return false; |
| 81 | |
| 82 | Gjs::AutoChar full_function_name{ |
| 83 | g_strdup_printf("%s_%s", ns_name, class_name)}; |
| 84 | JSFunction* constructor_fun = JS_NewFunction( |
| 85 | cx, constructor_native, nargs, JSFUN_CONSTRUCTOR, full_function_name); |
| 86 | if (!constructor_fun) |
| 87 | return false; |
| 88 | |
| 89 | constructor.set(JS_GetFunctionObject(constructor_fun)); |
| 90 | |
| 91 | if (static_ps && !JS_DefineProperties(cx, constructor, static_ps)) |
| 92 | return false; |
| 93 | if (static_fs && !JS_DefineFunctions(cx, constructor, static_fs)) |
| 94 | return false; |
| 95 | |
| 96 | if (!JS_LinkConstructorAndPrototype(cx, constructor, prototype)) |
| 97 | return false; |
| 98 | |
| 99 | // The constructor defined by JS_InitClass() has no property attributes, but |
no test coverage detected