Diff
Modified: trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.cpp (233759 => 233760)
--- trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.cpp 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.cpp 2018-07-12 05:18:20 UTC (rev 233760)
@@ -53,7 +53,7 @@
const ClassInfo JSCCallbackFunction::s_info = { "CallbackFunction", &InternalFunction::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCCallbackFunction) };
-JSCCallbackFunction* JSCCallbackFunction::create(VM& vm, JSGlobalObject* globalObject, const String& name, Type type, JSCClass* jscClass, GRefPtr<GClosure>&& closure, GType returnType, Vector<GType>&& parameters)
+JSCCallbackFunction* JSCCallbackFunction::create(VM& vm, JSGlobalObject* globalObject, const String& name, Type type, JSCClass* jscClass, GRefPtr<GClosure>&& closure, GType returnType, std::optional<Vector<GType>>&& parameters)
{
Structure* structure = globalObject->glibCallbackFunctionStructure();
JSCCallbackFunction* function = new (NotNull, allocateCell<JSCCallbackFunction>(vm.heap)) JSCCallbackFunction(vm, structure, type, jscClass, WTFMove(closure), returnType, WTFMove(parameters));
@@ -61,7 +61,7 @@
return function;
}
-JSCCallbackFunction::JSCCallbackFunction(VM& vm, Structure* structure, Type type, JSCClass* jscClass, GRefPtr<GClosure>&& closure, GType returnType, Vector<GType>&& parameters)
+JSCCallbackFunction::JSCCallbackFunction(VM& vm, Structure* structure, Type type, JSCClass* jscClass, GRefPtr<GClosure>&& closure, GType returnType, std::optional<Vector<GType>>&& parameters)
: InternalFunction(vm, structure, APICallbackFunction::call<JSCCallbackFunction>, type == Type::Constructor ? APICallbackFunction::construct<JSCCallbackFunction> : nullptr)
, m_functionCallback(callAsFunction)
, m_constructCallback(callAsConstructor)
@@ -99,9 +99,9 @@
auto callbackData = jscContextPushCallback(context.get(), toRef(this), thisObject, argumentCount, arguments);
// GClosure always expect to have at least the instance parameter.
- bool addInstance = instance || m_parameters.isEmpty();
+ bool addInstance = instance || (m_parameters && m_parameters->isEmpty());
- auto parameterCount = std::min(m_parameters.size(), argumentCount);
+ auto parameterCount = m_parameters ? std::min(m_parameters->size(), argumentCount) : 1;
if (addInstance)
parameterCount++;
auto* values = static_cast<GValue*>(g_alloca(sizeof(GValue) * parameterCount));
@@ -113,8 +113,16 @@
g_value_set_pointer(&values[0], instance);
firstParameter = 1;
}
- for (size_t i = firstParameter; i < parameterCount && !*exception; ++i)
- jscContextJSValueToGValue(context.get(), arguments[i - firstParameter], m_parameters[i - firstParameter], &values[i], exception);
+ if (m_parameters) {
+ for (size_t i = firstParameter; i < parameterCount && !*exception; ++i)
+ jscContextJSValueToGValue(context.get(), arguments[i - firstParameter], m_parameters.value()[i - firstParameter], &values[i], exception);
+ } else {
+ auto* parameters = g_ptr_array_new_full(argumentCount, g_object_unref);
+ for (size_t i = 0; i < argumentCount; ++i)
+ g_ptr_array_add(parameters, jscContextGetOrCreateValue(context.get(), arguments[i]).leakRef());
+ g_value_init(&values[firstParameter], G_TYPE_PTR_ARRAY);
+ g_value_take_boxed(&values[firstParameter], parameters);
+ }
GValue returnValue = G_VALUE_INIT;
if (m_returnType != G_TYPE_NONE)
@@ -155,7 +163,7 @@
GValue returnValue = G_VALUE_INIT;
g_value_init(&returnValue, m_returnType);
- if (m_parameters.isEmpty()) {
+ if (m_parameters && m_parameters->isEmpty()) {
// GClosure always expect to have at least the instance parameter.
GValue dummyValue = G_VALUE_INIT;
g_value_init(&dummyValue, G_TYPE_POINTER);
@@ -162,12 +170,20 @@
g_closure_invoke(m_closure.get(), &returnValue, 1, &dummyValue, nullptr);
g_value_unset(&dummyValue);
} else {
- auto parameterCount = std::min(m_parameters.size(), argumentCount);
+ auto parameterCount = m_parameters ? std::min(m_parameters->size(), argumentCount) : 1;
auto* values = static_cast<GValue*>(g_alloca(sizeof(GValue) * parameterCount));
memset(values, 0, sizeof(GValue) * parameterCount);
- for (size_t i = 0; i < parameterCount && !*exception; ++i)
- jscContextJSValueToGValue(context.get(), arguments[i], m_parameters[i], &values[i], exception);
+ if (m_parameters) {
+ for (size_t i = 0; i < parameterCount && !*exception; ++i)
+ jscContextJSValueToGValue(context.get(), arguments[i], m_parameters.value()[i], &values[i], exception);
+ } else {
+ auto* parameters = g_ptr_array_new_full(argumentCount, g_object_unref);
+ for (size_t i = 0; i < argumentCount; ++i)
+ g_ptr_array_add(parameters, jscContextGetOrCreateValue(context.get(), arguments[i]).leakRef());
+ g_value_init(&values[0], G_TYPE_PTR_ARRAY);
+ g_value_take_boxed(&values[0], parameters);
+ }
if (!*exception)
g_closure_invoke(m_closure.get(), &returnValue, parameterCount, values, nullptr);
Modified: trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.h (233759 => 233760)
--- trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.h 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.h 2018-07-12 05:18:20 UTC (rev 233760)
@@ -52,7 +52,7 @@
Constructor
};
- static JSCCallbackFunction* create(VM&, JSGlobalObject*, const String& name, Type, JSCClass*, GRefPtr<GClosure>&&, GType, Vector<GType>&&);
+ static JSCCallbackFunction* create(VM&, JSGlobalObject*, const String& name, Type, JSCClass*, GRefPtr<GClosure>&&, GType, std::optional<Vector<GType>>&&);
static void destroy(JSCell*);
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
@@ -69,7 +69,7 @@
private:
static IsoSubspace* subspaceForImpl(VM&);
- JSCCallbackFunction(VM&, Structure*, Type, JSCClass*, GRefPtr<GClosure>&&, GType, Vector<GType>&&);
+ JSCCallbackFunction(VM&, Structure*, Type, JSCClass*, GRefPtr<GClosure>&&, GType, std::optional<Vector<GType>>&&);
JSObjectCallAsFunctionCallback functionCallback() { return m_functionCallback; }
JSObjectCallAsConstructorCallback constructCallback() { return m_constructCallback; }
@@ -80,7 +80,7 @@
GRefPtr<JSCClass> m_class;
GRefPtr<GClosure> m_closure;
GType m_returnType;
- Vector<GType> m_parameters;
+ std::optional<Vector<GType>> m_parameters;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/API/glib/JSCClass.cpp (233759 => 233760)
--- trunk/Source/_javascript_Core/API/glib/JSCClass.cpp 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/API/glib/JSCClass.cpp 2018-07-12 05:18:20 UTC (rev 233760)
@@ -521,7 +521,7 @@
return jscClass->priv->parentClass;
}
-static GRefPtr<JSCValue> jscClassCreateConstructor(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, Vector<GType>&& parameters)
+static GRefPtr<JSCValue> jscClassCreateConstructor(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, std::optional<Vector<GType>>&& parameters)
{
JSCClassPrivate* priv = jscClass->priv;
GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
@@ -555,7 +555,7 @@
* parameters and @user_data as the last parameter. When the constructor object is cleared in the #JSCClass context,
* @destroy_notify is called with @user_data as parameter.
*
- * This function creates the constructor, that needs to be added to an object as a property to be able to use it. Use
+ * This function creates the constructor, which needs to be added to an object as a property to be able to use it. Use
* jsc_context_set_value() to make the constructor available in the global object.
*
* Returns: (transfer full): a #JSCValue representing the class constructor.
@@ -601,7 +601,7 @@
* parameters and @user_data as the last parameter. When the constructor object is cleared in the #JSCClass context,
* @destroy_notify is called with @user_data as parameter.
*
- * This function creates the constructor, that needs to be added to an object as a property to be able to use it. Use
+ * This function creates the constructor, which needs to be added to an object as a property to be able to use it. Use
* jsc_context_set_value() to make the constructor available in the global object.
*
* Returns: (transfer full): a #JSCValue representing the class constructor.
@@ -628,9 +628,42 @@
return jscClassCreateConstructor(jscClass, name ? name : priv->name.data(), callback, userData, destroyNotify, returnType, WTFMove(parameters)).leakRef();
}
-static void jscClassAddMethod(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, Vector<GType>&& parameters)
+/**
+ * jsc_class_add_constructor_variadic:
+ * @jsc_class: a #JSCClass
+ * @name: (nullable): the constructor name or %NULL
+ * @callback: (scope async): a #GCallback to be called to create an instance of @jsc_class
+ * @user_data: (closure): user data to pass to @callback
+ * @destroy_notify: (nullable): destroy notifier for @user_data
+ * @return_type: the #GType of the constructor return value
+ *
+ * Add a constructor to @jsc_class. If @name is %NULL, the class name will be used. When <function>new</function>
+ * is used with the constructor or jsc_value_constructor_call() is called, @callback is invoked receiving
+ * a #GPtrArray of #JSCValue<!-- -->s as arguments and @user_data as the last parameter. When the constructor object
+ * is cleared in the #JSCClass context, @destroy_notify is called with @user_data as parameter.
+ *
+ * This function creates the constructor, which needs to be added to an object as a property to be able to use it. Use
+ * jsc_context_set_value() to make the constructor available in the global object.
+ *
+ * Returns: (transfer full): a #JSCValue representing the class constructor.
+ */
+JSCValue* jsc_class_add_constructor_variadic(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType)
{
+ g_return_val_if_fail(JSC_IS_CLASS(jscClass), nullptr);
+ g_return_val_if_fail(callback, nullptr);
+
JSCClassPrivate* priv = jscClass->priv;
+ g_return_val_if_fail(jscClass->priv->context, nullptr);
+
+ if (!name)
+ name = priv->name.data();
+
+ return jscClassCreateConstructor(jscClass, name ? name : priv->name.data(), callback, userData, destroyNotify, returnType, std::nullopt).leakRef();
+}
+
+static void jscClassAddMethod(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, std::optional<Vector<GType>>&& parameters)
+{
+ JSCClassPrivate* priv = jscClass->priv;
GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
JSC::ExecState* exec = toJS(jscContextGetJSContext(priv->context));
JSC::VM& vm = exec->vm();
@@ -714,6 +747,30 @@
}
/**
+ * jsc_class_add_method_variadic:
+ * @jsc_class: a #JSCClass
+ * @name: the method name
+ * @callback: (scope async): a #GCallback to be called to invoke method @name of @jsc_class
+ * @user_data: (closure): user data to pass to @callback
+ * @destroy_notify: (nullable): destroy notifier for @user_data
+ * @return_type: the #GType of the method return value, or %G_TYPE_NONE if the method is void.
+ *
+ * Add method with @name to @jsc_class. When the method is called by _javascript_ or jsc_value_object_invoke_method(),
+ * @callback is called receiving the class instance as first parameter, followed by a #GPtrArray of #JSCValue<!-- -->s
+ * with the method arguments and then @user_data as last parameter. When the method is cleared in the #JSCClass context,
+ * @destroy_notify is called with @user_data as parameter.
+ */
+void jsc_class_add_method_variadic(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType)
+{
+ g_return_if_fail(JSC_IS_CLASS(jscClass));
+ g_return_if_fail(name);
+ g_return_if_fail(callback);
+ g_return_if_fail(jscClass->priv->context);
+
+ jscClassAddMethod(jscClass, name, callback, userData, destroyNotify, returnType, std::nullopt);
+}
+
+/**
* jsc_class_add_property:
* @jsc_class: a #JSCClass
* @name: the property name
Modified: trunk/Source/_javascript_Core/API/glib/JSCClass.h (233759 => 233760)
--- trunk/Source/_javascript_Core/API/glib/JSCClass.h 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/API/glib/JSCClass.h 2018-07-12 05:18:20 UTC (rev 233760)
@@ -76,63 +76,79 @@
} JSCClassVTable;
JSC_API GType
-jsc_class_get_type (void);
+jsc_class_get_type (void);
JSC_API const char *
-jsc_class_get_name (JSCClass *jsc_class);
+jsc_class_get_name (JSCClass *jsc_class);
JSC_API JSCClass *
-jsc_class_get_parent (JSCClass *jsc_class);
+jsc_class_get_parent (JSCClass *jsc_class);
JSC_API JSCValue *
-jsc_class_add_constructor (JSCClass *jsc_class,
- const char *name,
- GCallback callback,
- gpointer user_data,
- GDestroyNotify destroy_notify,
- GType return_type,
- guint n_params,
- ...);
+jsc_class_add_constructor (JSCClass *jsc_class,
+ const char *name,
+ GCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GType return_type,
+ guint n_params,
+ ...);
JSC_API JSCValue *
-jsc_class_add_constructorv (JSCClass *jsc_class,
- const char *name,
- GCallback callback,
- gpointer user_data,
- GDestroyNotify destroy_notify,
- GType return_type,
- guint n_parameters,
- GType *parameter_types);
+jsc_class_add_constructorv (JSCClass *jsc_class,
+ const char *name,
+ GCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GType return_type,
+ guint n_parameters,
+ GType *parameter_types);
+JSC_API JSCValue *
+jsc_class_add_constructor_variadic (JSCClass *jsc_class,
+ const char *name,
+ GCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GType return_type);
+
JSC_API void
-jsc_class_add_method (JSCClass *jsc_class,
- const char *name,
- GCallback callback,
- gpointer user_data,
- GDestroyNotify destroy_notify,
- GType return_type,
- guint n_params,
- ...);
+jsc_class_add_method (JSCClass *jsc_class,
+ const char *name,
+ GCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GType return_type,
+ guint n_params,
+ ...);
JSC_API void
-jsc_class_add_methodv (JSCClass *jsc_class,
- const char *name,
- GCallback callback,
- gpointer user_data,
- GDestroyNotify destroy_notify,
- GType return_type,
- guint n_parameters,
- GType *parameter_types);
+jsc_class_add_methodv (JSCClass *jsc_class,
+ const char *name,
+ GCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GType return_type,
+ guint n_parameters,
+ GType *parameter_types);
JSC_API void
-jsc_class_add_property (JSCClass *jsc_class,
- const char *name,
- GType property_type,
- GCallback getter,
- GCallback setter,
- gpointer user_data,
- GDestroyNotify destroy_notify);
+jsc_class_add_method_variadic (JSCClass *jsc_class,
+ const char *name,
+ GCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GType return_type);
+JSC_API void
+jsc_class_add_property (JSCClass *jsc_class,
+ const char *name,
+ GType property_type,
+ GCallback getter,
+ GCallback setter,
+ gpointer user_data,
+ GDestroyNotify destroy_notify);
+
G_END_DECLS
#endif /* JSCClass_h */
Modified: trunk/Source/_javascript_Core/API/glib/JSCValue.cpp (233759 => 233760)
--- trunk/Source/_javascript_Core/API/glib/JSCValue.cpp 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/API/glib/JSCValue.cpp 2018-07-12 05:18:20 UTC (rev 233760)
@@ -1089,7 +1089,7 @@
if (getter) {
GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(getter, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
auto* functionObject = toRef(JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), "get"_s,
- JSC::JSCCallbackFunction::Type::Method, nullptr, WTFMove(closure), propertyType, { }));
+ JSC::JSCCallbackFunction::Type::Method, nullptr, WTFMove(closure), propertyType, Vector<GType> { }));
GRefPtr<JSCValue> function = jscContextGetOrCreateValue(priv->context.get(), functionObject);
jsc_value_object_set_property(descriptor.get(), "get", function.get());
}
@@ -1096,7 +1096,7 @@
if (setter) {
GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(setter, userData, getter ? nullptr : reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
auto* functionObject = toRef(JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), "set"_s,
- JSC::JSCCallbackFunction::Type::Method, nullptr, WTFMove(closure), G_TYPE_NONE, { propertyType }));
+ JSC::JSCCallbackFunction::Type::Method, nullptr, WTFMove(closure), G_TYPE_NONE, Vector<GType> { propertyType }));
GRefPtr<JSCValue> function = jscContextGetOrCreateValue(priv->context.get(), functionObject);
jsc_value_object_set_property(descriptor.get(), "set", function.get());
}
@@ -1105,7 +1105,7 @@
JSC_TYPE_VALUE, value, G_TYPE_STRING, propertyName, JSC_TYPE_VALUE, descriptor.get(), G_TYPE_NONE));
}
-static GRefPtr<JSCValue> jscValueFunctionCreate(JSCContext* context, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, Vector<GType>&& parameters)
+static GRefPtr<JSCValue> jscValueFunctionCreate(JSCContext* context, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, std::optional<Vector<GType>>&& parameters)
{
GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify))));
JSC::ExecState* exec = toJS(jscContextGetJSContext(context));
@@ -1154,7 +1154,7 @@
/**
* jsc_value_new_functionv: (rename-to jsc_value_new_function)
- * @context: a #JSCContext:
+ * @context: a #JSCContext
* @name: (nullable): the function name or %NULL
* @callback: (scope async): a #GCallback.
* @user_data: (closure): user data to pass to @callback.
@@ -1187,6 +1187,30 @@
}
/**
+ * jsc_value_new_function_variadic:
+ * @context: a #JSCContext
+ * @name: (nullable): the function name or %NULL
+ * @callback: (scope async): a #GCallback.
+ * @user_data: (closure): user data to pass to @callback.
+ * @destroy_notify: (nullable): destroy notifier for @user_data
+ * @return_type: the #GType of the function return value, or %G_TYPE_NONE if the function is void.
+ *
+ * Create a function in @context. If @name is %NULL an anonymous function will be created.
+ * When the function is called by _javascript_ or jsc_value_function_call(), @callback is called
+ * receiving an #GPtrArray of #JSCValue<!-- -->s with the arguments and then @user_data as last parameter.
+ * When the function is cleared in @context, @destroy_notify is called with @user_data as parameter.
+ *
+ * Returns: (transfer full): a #JSCValue.
+ */
+JSCValue* jsc_value_new_function_variadic(JSCContext* context, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType)
+{
+ g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr);
+ g_return_val_if_fail(callback, nullptr);
+
+ return jscValueFunctionCreate(context, name, callback, userData, destroyNotify, returnType, std::nullopt).leakRef();
+}
+
+/**
* jsc_value_is_function:
* @value: a #JSCValue
*
Modified: trunk/Source/_javascript_Core/API/glib/JSCValue.h (233759 => 233760)
--- trunk/Source/_javascript_Core/API/glib/JSCValue.h 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/API/glib/JSCValue.h 2018-07-12 05:18:20 UTC (rev 233760)
@@ -226,6 +226,14 @@
guint n_parameters,
GType *parameter_types);
+JSC_API JSCValue *
+jsc_value_new_function_variadic (JSCContext *context,
+ const char *name,
+ GCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify,
+ GType return_type);
+
JSC_API gboolean
jsc_value_is_function (JSCValue *value);
Modified: trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt (233759 => 233760)
--- trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/API/glib/docs/jsc-glib-4.0-sections.txt 2018-07-12 05:18:20 UTC (rev 233760)
@@ -99,6 +99,7 @@
jsc_value_object_define_property_accessor
jsc_value_new_function
jsc_value_new_functionv
+jsc_value_new_function_variadic
jsc_value_is_function
jsc_value_function_call
jsc_value_function_callv
@@ -178,8 +179,10 @@
jsc_class_get_parent
jsc_class_add_constructor
jsc_class_add_constructorv
+jsc_class_add_constructor_variadic
jsc_class_add_method
jsc_class_add_methodv
+jsc_class_add_method_variadic
jsc_class_add_property
<SUBSECTION Standard>
Modified: trunk/Source/_javascript_Core/ChangeLog (233759 => 233760)
--- trunk/Source/_javascript_Core/ChangeLog 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-07-12 05:18:20 UTC (rev 233760)
@@ -1,5 +1,35 @@
2018-07-11 Carlos Garcia Campos <[email protected]>
+ [GLIB] Add API to allow creating variadic functions
+ https://bugs.webkit.org/show_bug.cgi?id=187517
+
+ Reviewed by Michael Catanzaro.
+
+ Add a _variadic alternate method for jsc_class_add_constructor, jsc_class_add_method and
+ jsc_value_new_function. In that case the callback always receives a GPtrArray of JSCValue.
+
+ * API/glib/JSCCallbackFunction.cpp:
+ (JSC::JSCCallbackFunction::create): Make the parameters optional.
+ (JSC::JSCCallbackFunction::JSCCallbackFunction): Ditto.
+ (JSC::JSCCallbackFunction::call): Handle the case of parameters being nullopt by creating a GPtrArray of
+ JSCValue for the arguments.
+ (JSC::JSCCallbackFunction::construct): Ditto.
+ * API/glib/JSCCallbackFunction.h:
+ * API/glib/JSCClass.cpp:
+ (jscClassCreateConstructor): Make the parameters optional.
+ (jsc_class_add_constructor_variadic): Pass nullopt as parameters to jscClassCreateConstructor.
+ (jscClassAddMethod): Make the parameters optional.
+ (jsc_class_add_method_variadic): Pass nullopt as parameters to jscClassAddMethod.
+ * API/glib/JSCClass.h:
+ * API/glib/JSCValue.cpp:
+ (jsc_value_object_define_property_accessor): Update now that parameters are optional.
+ (jscValueFunctionCreate): Make the parameters optional.
+ (jsc_value_new_function_variadic): Pass nullopt as parameters to jscValueFunctionCreate.
+ * API/glib/JSCValue.h:
+ * API/glib/docs/jsc-glib-4.0-sections.txt:
+
+2018-07-11 Carlos Garcia Campos <[email protected]>
+
[GLIB] Add jsc_context_get_global_object() to GLib API
https://bugs.webkit.org/show_bug.cgi?id=187515
Modified: trunk/Tools/ChangeLog (233759 => 233760)
--- trunk/Tools/ChangeLog 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Tools/ChangeLog 2018-07-12 05:18:20 UTC (rev 233760)
@@ -1,5 +1,19 @@
2018-07-11 Carlos Garcia Campos <[email protected]>
+ [GLIB] Add API to allow creating variadic functions
+ https://bugs.webkit.org/show_bug.cgi?id=187517
+
+ Reviewed by Michael Catanzaro.
+
+ Add test cases.
+
+ * TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
+ (testJSCFunction):
+ (fooCreateWithFooV):
+ (multiplyFooV):
+
+2018-07-11 Carlos Garcia Campos <[email protected]>
+
[GLIB] Add jsc_context_get_global_object() to GLib API
https://bugs.webkit.org/show_bug.cgi?id=187515
Modified: trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp (233759 => 233760)
--- trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp 2018-07-12 05:13:56 UTC (rev 233759)
+++ trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp 2018-07-12 05:18:20 UTC (rev 233760)
@@ -867,6 +867,27 @@
g_assert_true(jsc_value_is_undefined(value.get()));
g_assert_did_throw(exceptionHandler, didThrow);
}
+
+ {
+ LeakChecker checker;
+ GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+ checker.watch(context.get());
+ ExceptionHandler exceptionHandler(context.get());
+
+ GRefPtr<JSCValue> function = adoptGRef(jsc_value_new_function_variadic(context.get(), "sumFunction", G_CALLBACK(sumFunction), nullptr, nullptr, G_TYPE_INT));
+ checker.watch(function.get());
+ jsc_context_set_value(context.get(), "sumFunction", function.get());
+
+ GRefPtr<JSCValue> value = adoptGRef(jsc_context_evaluate(context.get(), "sumFunction(2,4,6)", -1));
+ checker.watch(value.get());
+ g_assert_true(jsc_value_is_number(value.get()));
+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 12);
+
+ value = adoptGRef(jsc_context_evaluate(context.get(), "sumFunction()", -1));
+ checker.watch(value.get());
+ g_assert_true(jsc_value_is_number(value.get()));
+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 0);
+ }
}
static void testJSCObject()
@@ -1159,6 +1180,19 @@
return f;
}
+static Foo* fooCreateWithFooV(GPtrArray* values)
+{
+ auto* f = fooCreate();
+ g_ptr_array_foreach(values, [](gpointer data, gpointer userData) {
+ g_assert_true(JSC_IS_VALUE(data));
+ JSCValue* item = JSC_VALUE(data);
+ g_assert_true(jsc_value_is_number(item));
+ auto* foo = static_cast<Foo*>(userData);
+ foo->foo += jsc_value_to_int32(item);
+ }, f);
+ return f;
+}
+
static void fooFree(Foo* foo)
{
foo->~Foo();
@@ -1190,6 +1224,17 @@
foo->foo *= multiplier;
}
+static void multiplyFooV(Foo* foo, GPtrArray* multipliers)
+{
+ g_ptr_array_foreach(multipliers, [](gpointer data, gpointer userData) {
+ g_assert_true(JSC_IS_VALUE(data));
+ JSCValue* item = JSC_VALUE(data);
+ g_assert_true(jsc_value_is_number(item));
+ auto* foo = static_cast<Foo*>(userData);
+ foo->foo *= jsc_value_to_int32(item);
+ }, foo);
+}
+
static int fooGetProperty(Foo* foo, const char* name)
{
auto addResult = foo->properties.add(name, 0);
@@ -1413,6 +1458,21 @@
g_assert_true(jsc_value_is_number(value.get()));
g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 45);
+ jsc_class_add_method_variadic(jscClass, "multiply", G_CALLBACK(multiplyFooV), nullptr, nullptr, G_TYPE_NONE);
+ g_assert_true(jsc_value_object_has_property(foo.get(), "multiply"));
+ value = adoptGRef(jsc_context_evaluate(context.get(), "f.setFoo(1); f.multiply(1,2,3);", -1));
+ checker.watch(value.get());
+ value = adoptGRef(jsc_value_object_invoke_method(foo.get(), "getFoo", G_TYPE_NONE));
+ checker.watch(value.get());
+ g_assert_true(jsc_value_is_number(value.get()));
+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 6);
+ value = adoptGRef(jsc_context_evaluate(context.get(), "f.multiply()", -1));
+ checker.watch(value.get());
+ value = adoptGRef(jsc_value_object_invoke_method(foo.get(), "getFoo", G_TYPE_NONE));
+ checker.watch(value.get());
+ g_assert_true(jsc_value_is_number(value.get()));
+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 6);
+
GRefPtr<JSCValue> constructor2 = adoptGRef(jsc_class_add_constructorv(jscClass, "CreateWithFoo", G_CALLBACK(fooCreateWithFoo), nullptr, nullptr, G_TYPE_POINTER, 1, parameterTypes));
checker.watch(constructor2.get());
g_assert_true(jsc_value_is_constructor(constructor2.get()));
@@ -1450,6 +1510,29 @@
g_assert_true(jsc_value_is_number(value.get()));
g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 52);
+ GRefPtr<JSCValue> constructorV = adoptGRef(jsc_class_add_constructor_variadic(jscClass, "CreateWithFoo", G_CALLBACK(fooCreateWithFooV), nullptr, nullptr, G_TYPE_POINTER));
+ checker.watch(constructorV.get());
+ g_assert_true(jsc_value_is_constructor(constructorV.get()));
+ jsc_value_object_set_property(constructor.get(), "CreateWithFooV", constructorV.get());
+
+ GRefPtr<JSCValue> foo3 = adoptGRef(jsc_context_evaluate(context.get(), "f3 = new Foo.CreateWithFooV(10,20,30,40);", -1));
+ checker.watch(foo3.get());
+ g_assert_true(jsc_value_is_object(foo3.get()));
+ g_assert_true(jsc_value_object_is_instance_of(foo3.get(), jsc_class_get_name(jscClass)));
+ value = adoptGRef(jsc_context_evaluate(context.get(), "f3.foo", -1));
+ checker.watch(value.get());
+ g_assert_true(jsc_value_is_number(value.get()));
+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 100);
+
+ GRefPtr<JSCValue> foo4 = adoptGRef(jsc_context_evaluate(context.get(), "f4 = new Foo.CreateWithFooV();", -1));
+ checker.watch(foo4.get());
+ g_assert_true(jsc_value_is_object(foo4.get()));
+ g_assert_true(jsc_value_object_is_instance_of(foo3.get(), jsc_class_get_name(jscClass)));
+ value = adoptGRef(jsc_context_evaluate(context.get(), "f4.foo", -1));
+ checker.watch(value.get());
+ g_assert_true(jsc_value_is_number(value.get()));
+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 0);
+
JSCClass* otherClass = jsc_context_register_class(context.get(), "Baz", nullptr, nullptr, g_free);
checker.watch(otherClass);
g_assert_false(jsc_class_get_parent(otherClass));