42#define DECLARE_GUIPROXY(Type) \
43void Type::CreateJSObject() \
45 ScriptRequest rq(m_pGUI.GetScriptInterface()); \
46 using ProxyHandler = JSI_GUIProxy<std::remove_pointer_t<decltype(this)>>; \
47 m_JSObject = ProxyHandler::CreateJSObject(rq, this, GetGUI().GetProxyData(&ProxyHandler::Singleton())); \
49template class JSI_GUIProxy<Type>;
57 static JSClass c = PROXY_CLASS_DEF(
"GUIObjectProxy", JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy) | JSCLASS_HAS_RESERVED_SLOTS(1));
67 virtual bool has(
const std::string& name)
const override
72 virtual JSObject*
get(
const std::string& name)
const override
79 m_Functions[name].init(rq.
cx, JS_GetFunctionObject(function));
84 std::unordered_map<std::string, JS::PersistentRootedObject>
m_Functions;
89IGUIObject* IGUIProxyObject::FromPrivateSlot<IGUIObject>(JSObject* obj)
95 return UnsafeFromPrivateSlot<IGUIObject>(obj);
109 return IGUIProxyObject::UnsafeFromPrivateSlot<T>(args.thisv().toObjectOrNull());
117 const PropertyCache* data =
static_cast<const PropertyCache*
>(
static_cast<const GUIProxyProps*
>(js::GetProxyReservedSlot(proxy, 0).toPrivate()));
118 if (data->has(propName))
120 vp.setObjectOrNull(data->get(propName));
130 PropertyCache* data =
new PropertyCache();
137 if constexpr (!std::is_same_v<T, IGUIObject>)
138 CreateFunctions(rq, data);
143template<auto callable>
146 cache->
setFunction(rq, name, ScriptFunction::Create<callable, FromPrivateSlot>(rq, name.c_str()));
152 js::ProxyOptions options;
155 auto ret = std::make_unique<IGUIProxyObject>();
158 JS::RootedValue cppObj(rq.
cx), data(rq.
cx);
159 cppObj.get().setPrivate(ret->m_Ptr);
160 data.get().setPrivate(
static_cast<void*
>(dataPtr));
161 ret->m_Object.init(rq.
cx, js::NewProxyObject(rq.
cx, &
Singleton(), cppObj,
nullptr, options));
162 js::SetProxyReservedSlot(ret->m_Object, 0, data);
167bool JSI_GUIProxy<T>::get(JSContext* cx, JS::HandleObject proxy, JS::HandleValue
UNUSED(receiver), JS::HandleId
id, JS::MutableHandleValue vp)
const
171 T* e = IGUIProxyObject::FromPrivateSlot<T>(proxy.get());
175 JS::RootedValue idval(rq.
cx);
176 if (!JS_IdToValue(rq.
cx,
id, &idval))
179 std::string propName;
184 if (PropGetter(proxy, propName, vp))
188 if (propName.substr(0, 2) ==
"on")
190 CStr eventName(propName.substr(2));
191 std::map<CStr, JS::Heap<JSObject*>>::iterator it = e->m_ScriptHandlers.find(eventName);
192 if (it == e->m_ScriptHandlers.end())
195 vp.setObject(*it->second.get());
199 if (propName ==
"parent")
206 vp.set(JS::NullValue());
210 else if (propName ==
"children")
214 for (
size_t i = 0; i < e->m_Children.size(); ++i)
219 else if (propName ==
"name")
224 else if (e->SettingExists(propName))
226 e->m_Settings[propName]->ToJSVal(rq, vp);
230 LOGERROR(
"Property '%s' does not exist!", propName.c_str());
237 JS::HandleValue
UNUSED(receiver), JS::ObjectOpResult& result)
const
239 T* e = IGUIProxyObject::FromPrivateSlot<T>(proxy.get());
242 LOGERROR(
"C++ GUI Object could not be found");
243 return result.fail(JSMSG_OBJECT_REQUIRED);
248 JS::RootedValue idval(rq.
cx);
249 if (!JS_IdToValue(rq.
cx,
id, &idval))
250 return result.fail(JSMSG_BAD_PROP_ID);
252 std::string propName;
254 return result.fail(JSMSG_BAD_PROP_ID);
256 if (propName ==
"name")
260 return result.fail(JSMSG_BAD_PROP_ID);
262 return result.succeed();
265 JS::RootedObject vpObj(cx);
267 vpObj = &vp.toObject();
270 if (propName.substr(0, 2) ==
"on")
272 if (vp.isPrimitive() || vp.isNull() || !JS_ObjectIsFunction(&vp.toObject()))
274 LOGERROR(
"on- event-handlers must be functions");
275 return result.fail(JSMSG_NOT_FUNCTION);
278 CStr eventName(propName.substr(2));
279 e->SetScriptHandler(eventName, vpObj);
281 return result.succeed();
284 if (e->SettingExists(propName))
285 return e->m_Settings[propName]->FromJSVal(rq, vp,
true) ? result.succeed() : result.fail(JSMSG_USER_DEFINED_ERROR);
287 LOGERROR(
"Property '%s' does not exist!", propName.c_str());
288 return result.fail(JSMSG_BAD_PROP_ID);
294 T* e = IGUIProxyObject::FromPrivateSlot<T>(proxy.get());
297 LOGERROR(
"C++ GUI Object could not be found");
298 return result.fail(JSMSG_OBJECT_REQUIRED);
303 JS::RootedValue idval(rq.
cx);
304 if (!JS_IdToValue(rq.
cx,
id, &idval))
305 return result.fail(JSMSG_BAD_PROP_ID);
307 std::string propName;
309 return result.fail(JSMSG_BAD_PROP_ID);
312 if (std::string_view{propName}.substr(0, 2) ==
"on")
314 CStr eventName(propName.substr(2));
315 e->UnsetScriptHandler(eventName);
316 return result.succeed();
319 LOGERROR(
"Only event handlers can be deleted from GUI objects!");
320 return result.fail(JSMSG_BAD_PROP_ID);
#define LOGERROR(...)
Definition: CLogger.h:37
Proxies need to store some data whose lifetime is tied to an interface.
Definition: JSInterface_GUIProxy.h:86
virtual bool setFunction(const ScriptRequest &rq, const std::string &name, JSFunction *function)=0
GUI object such as a button or an input-box.
Definition: IGUIObject.h:60
IGUIObject * GetParent() const
NOTE! This will not just return m_pParent, when that is need use it! There is one exception to it,...
Definition: IGUIObject.cpp:187
JSObject * GetJSObject()
Retrieves the JSObject representing this GUI object.
Definition: IGUIObject.cpp:427
Handles the js interface with C++ GUI objects.
Definition: JSInterface_GUIProxy.h:121
virtual bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleValue receiver, JS::HandleId id, JS::MutableHandleValue vp) const override final
Definition: JSInterface_GUIProxy_impl.h:167
static std::unique_ptr< IGUIProxyObject > CreateJSObject(const ScriptRequest &rq, GUIObjectType *ptr, GUIProxyProps *data)
Definition: JSInterface_GUIProxy_impl.h:150
bool PropGetter(JS::HandleObject proxy, const std::string &propName, JS::MutableHandleValue vp) const
Definition: JSInterface_GUIProxy_impl.h:113
static JSI_GUIProxy & Singleton()
Definition: JSInterface_GUIProxy_impl.h:35
static GUIObjectType * FromPrivateSlot(const ScriptRequest &, JS::CallArgs &args)
Definition: JSInterface_GUIProxy_impl.h:106
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue vp, JS::HandleValue receiver, JS::ObjectOpResult &result) const final
Definition: JSInterface_GUIProxy_impl.h:236
static void CreateFunctions(const ScriptRequest &rq, GUIProxyProps *cache)
virtual bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::ObjectOpResult &result) const override final
Definition: JSInterface_GUIProxy_impl.h:292
static std::pair< const js::BaseProxyHandler *, GUIProxyProps * > CreateData(ScriptInterface &scriptInterface)
Definition: JSInterface_GUIProxy_impl.h:127
static void CreateFunction(const ScriptRequest &rq, GUIProxyProps *cache, const std::string &name)
Definition: JSInterface_GUIProxy_impl.h:144
Definition: JSInterface_GUIProxy_impl.h:63
virtual JSObject * get(const std::string &name) const override
Definition: JSInterface_GUIProxy_impl.h:72
virtual ~MapCache()
Definition: JSInterface_GUIProxy_impl.h:65
virtual bool setFunction(const ScriptRequest &rq, const std::string &name, JSFunction *function) override
Definition: JSInterface_GUIProxy_impl.h:77
std::unordered_map< std::string, JS::PersistentRootedObject > m_Functions
Definition: JSInterface_GUIProxy_impl.h:84
virtual bool has(const std::string &name) const override
Definition: JSInterface_GUIProxy_impl.h:67
Abstraction around a SpiderMonkey JS::Realm.
Definition: ScriptInterface.h:72
Spidermonkey maintains some 'local' state via the JSContext* object.
Definition: ScriptRequest.h:60
JSContext * cx
Definition: ScriptRequest.h:92
Template base class for singletons.
Definition: Singleton.h:34
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning.
Definition: code_annotation.h:40
Definition: JSInterface_GUIProxy_impl.h:53
JSClass & ClassDefinition()
Definition: JSInterface_GUIProxy_impl.h:55
bool FromJSVal(const ScriptRequest &rq, const JS::HandleValue val, T &ret)
Convert a JS::Value to a C++ type.
void ToJSVal(const ScriptRequest &rq, JS::MutableHandleValue ret, T const &val)
Convert a C++ type to a JS::Value.
bool CreateArray(const ScriptRequest &rq, JS::MutableHandleValue objectValue, size_t length=0)
Sets the given value to a new JS object or Null Value in case of out-of-memory.
Definition: Object.h:244
bool SetPropertyInt(const ScriptRequest &rq, JS::HandleValue obj, int name, const T &value, bool constant=false, bool enumerable=true)
Definition: Object.h:129
#define T(string_literal)
Definition: secure_crt.cpp:77
Definition: JSInterface_GUIProxy_impl.h:101