WebKit Bugzilla
Attachment 340080 Details for
Bug 185508
: [JSC][GLIB] Add introspectable alternatives to functions using vargars
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
jsc-api-varargs.diff (text/plain), 43.93 KB, created by
Carlos Garcia Campos
on 2018-05-10 03:48:37 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Carlos Garcia Campos
Created:
2018-05-10 03:48:37 PDT
Size:
43.93 KB
patch
obsolete
>diff --git a/Source/JavaScriptCore/API/glib/JSCClass.cpp b/Source/JavaScriptCore/API/glib/JSCClass.cpp >index 841d37ce6ef..3b52fea6365 100644 >--- a/Source/JavaScriptCore/API/glib/JSCClass.cpp >+++ b/Source/JavaScriptCore/API/glib/JSCClass.cpp >@@ -521,8 +521,26 @@ JSCClass* jsc_class_get_parent(JSCClass* jscClass) > return jscClass->priv->parentClass; > } > >+static GRefPtr<JSCValue> jscClassCreateConstructor(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, 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(); >+ JSC::JSLockHolder locker(vm); >+ auto* functionObject = JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), String::fromUTF8(name), >+ JSC::JSCCallbackFunction::Type::Constructor, jscClass, WTFMove(closure), returnType, WTFMove(parameters)); >+ auto constructor = jscContextGetOrCreateValue(priv->context, toRef(functionObject)); >+ GRefPtr<JSCValue> prototype = jscContextGetOrCreateValue(priv->context, toRef(priv->prototype.get())); >+ auto nonEnumerable = static_cast<JSCValuePropertyFlags>(JSC_VALUE_PROPERTY_CONFIGURABLE | JSC_VALUE_PROPERTY_WRITABLE); >+ jsc_value_object_define_property_data(constructor.get(), "prototype", nonEnumerable, prototype.get()); >+ jsc_value_object_define_property_data(prototype.get(), "constructor", nonEnumerable, constructor.get()); >+ priv->constructors.set(name, functionObject); >+ return constructor; >+} >+ > /** >- * jsc_class_add_constructor: >+ * jsc_class_add_constructor: (skip) > * @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 >@@ -563,23 +581,70 @@ JSCValue* jsc_class_add_constructor(JSCClass* jscClass, const char* name, GCallb > } > va_end(args); > >+ return jscClassCreateConstructor(jscClass, name ? name : priv->name.data(), callback, userData, destroyNotify, returnType, WTFMove(parameters)).leakRef(); >+ >+} >+ >+/** >+ * jsc_class_add_constructorv: (rename-to jsc_class_add_constructor) >+ * @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 >+ * @n_parameters: the number of parameters >+ * @parameter_types: (nullable) (array length=n_parameters) (element-type GType): a list of #GType<!-- -->s, one for each parameter, or %NULL >+ * >+ * 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 the >+ * 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 >+ * 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_constructorv(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, unsigned parametersCount, GType* parameterTypes) >+{ >+ g_return_val_if_fail(JSC_IS_CLASS(jscClass), nullptr); >+ g_return_val_if_fail(callback, nullptr); >+ g_return_val_if_fail(!parametersCount || parameterTypes, nullptr); >+ >+ JSCClassPrivate* priv = jscClass->priv; >+ g_return_val_if_fail(priv->context, nullptr); >+ >+ if (!name) >+ name = priv->name.data(); >+ >+ Vector<GType> parameters; >+ if (parametersCount) { >+ parameters.reserveInitialCapacity(parametersCount); >+ for (unsigned i = 0; i < parametersCount; ++i) >+ parameters.uncheckedAppend(parameterTypes[i]); >+ } >+ >+ 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) >+{ >+ 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(); > JSC::JSLockHolder locker(vm); >- auto* functionObject = JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), String::fromUTF8(name), >- JSC::JSCCallbackFunction::Type::Constructor, jscClass, WTFMove(closure), returnType, WTFMove(parameters)); >- auto constructor = jscContextGetOrCreateValue(priv->context, toRef(functionObject)); >+ auto* functionObject = toRef(JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), String::fromUTF8(name), >+ JSC::JSCCallbackFunction::Type::Method, jscClass, WTFMove(closure), returnType, WTFMove(parameters))); >+ auto method = jscContextGetOrCreateValue(priv->context, functionObject); > GRefPtr<JSCValue> prototype = jscContextGetOrCreateValue(priv->context, toRef(priv->prototype.get())); > auto nonEnumerable = static_cast<JSCValuePropertyFlags>(JSC_VALUE_PROPERTY_CONFIGURABLE | JSC_VALUE_PROPERTY_WRITABLE); >- jsc_value_object_define_property_data(constructor.get(), "prototype", nonEnumerable, prototype.get()); >- jsc_value_object_define_property_data(prototype.get(), "constructor", nonEnumerable, constructor.get()); >- priv->constructors.set(name, functionObject); >- return constructor.leakRef(); >+ jsc_value_object_define_property_data(prototype.get(), name, nonEnumerable, method.get()); > } > > /** >- * jsc_class_add_method: >+ * jsc_class_add_method: (skip) > * @jsc_class: a #JSCClass > * @name: the method name > * @callback: (scope async): a #GCallback to be called to invoke method @name of @jsc_class >@@ -599,9 +664,7 @@ void jsc_class_add_method(JSCClass* jscClass, const char* name, GCallback callba > g_return_if_fail(JSC_IS_CLASS(jscClass)); > g_return_if_fail(name); > g_return_if_fail(callback); >- >- JSCClassPrivate* priv = jscClass->priv; >- g_return_if_fail(priv->context); >+ g_return_if_fail(jscClass->priv->context); > > va_list args; > va_start(args, paramCount); >@@ -613,16 +676,41 @@ void jsc_class_add_method(JSCClass* jscClass, const char* name, GCallback callba > } > va_end(args); > >- 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(); >- JSC::JSLockHolder locker(vm); >- auto* functionObject = toRef(JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), String::fromUTF8(name), >- JSC::JSCCallbackFunction::Type::Method, jscClass, WTFMove(closure), returnType, WTFMove(parameters))); >- auto method = jscContextGetOrCreateValue(priv->context, functionObject); >- GRefPtr<JSCValue> prototype = jscContextGetOrCreateValue(priv->context, toRef(priv->prototype.get())); >- auto nonEnumerable = static_cast<JSCValuePropertyFlags>(JSC_VALUE_PROPERTY_CONFIGURABLE | JSC_VALUE_PROPERTY_WRITABLE); >- jsc_value_object_define_property_data(prototype.get(), name, nonEnumerable, method.get()); >+ jscClassAddMethod(jscClass, name, callback, userData, destroyNotify, returnType, WTFMove(parameters)); >+} >+ >+/** >+ * jsc_class_add_methodv: (rename-to jsc_class_add_method) >+ * @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. >+ * @n_parameters: the number of parameter types to follow or 0 if the method doesn't receive parameters. >+ * @parameter_types: (nullable) (array length=n_parameters) (element-type GType): a list of #GType<!-- -->s, one for each parameter, or %NULL >+ * >+ * 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 the method parameters 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_methodv(JSCClass* jscClass, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, unsigned parametersCount, GType *parameterTypes) >+{ >+ g_return_if_fail(JSC_IS_CLASS(jscClass)); >+ g_return_if_fail(name); >+ g_return_if_fail(callback); >+ g_return_if_fail(!parametersCount || parameterTypes); >+ g_return_if_fail(jscClass->priv->context); >+ >+ Vector<GType> parameters; >+ if (parametersCount) { >+ parameters.reserveInitialCapacity(parametersCount); >+ for (unsigned i = 0; i < parametersCount; ++i) >+ parameters.uncheckedAppend(parameterTypes[i]); >+ } >+ >+ jscClassAddMethod(jscClass, name, callback, userData, destroyNotify, returnType, WTFMove(parameters)); > } > > /** >diff --git a/Source/JavaScriptCore/API/glib/JSCClass.h b/Source/JavaScriptCore/API/glib/JSCClass.h >index 1ff849d8190..38a7fe9e35b 100644 >--- a/Source/JavaScriptCore/API/glib/JSCClass.h >+++ b/Source/JavaScriptCore/API/glib/JSCClass.h >@@ -76,42 +76,62 @@ typedef struct { > } 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, >- unsigned 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_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_API void >-jsc_class_add_method (JSCClass *jsc_class, >- const char *name, >- GCallback callback, >- gpointer user_data, >- GDestroyNotify destroy_notify, >- GType return_type, >- unsigned n_params, >- ...); >+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_property (JSCClass *jsc_class, >+ const char *name, >+ GType property_type, >+ GCallback getter, >+ GCallback setter, >+ gpointer user_data, >+ GDestroyNotify destroy_notify); > > G_END_DECLS > >diff --git a/Source/JavaScriptCore/API/glib/JSCValue.cpp b/Source/JavaScriptCore/API/glib/JSCValue.cpp >index 693ba104e61..4ba9d3e8b86 100644 >--- a/Source/JavaScriptCore/API/glib/JSCValue.cpp >+++ b/Source/JavaScriptCore/API/glib/JSCValue.cpp >@@ -457,7 +457,7 @@ GBytes* jsc_value_to_string_as_bytes(JSCValue* value) > } > > /** >- * jsc_value_new_array: >+ * jsc_value_new_array: (skip) > * @context: a #JSCContext > * @first_item_type: #GType of first item, or %G_TYPE_NONE > * @...: value of the first item, followed optionally by more type/value pairs, followed by %G_TYPE_NONE. >@@ -831,6 +831,22 @@ char** jsc_value_object_enumerate_properties(JSCValue* value) > return result; > } > >+static JSValueRef jsObjectCall(JSGlobalContextRef jsContext, JSObjectRef function, JSC::JSCCallbackFunction::Type functionType, JSObjectRef thisObject, const Vector<JSValueRef>& arguments, JSValueRef* exception) >+{ >+ switch (functionType) { >+ case JSC::JSCCallbackFunction::Type::Constructor: >+ return JSObjectCallAsConstructor(jsContext, function, arguments.size(), arguments.data(), exception); >+ break; >+ case JSC::JSCCallbackFunction::Type::Method: >+ ASSERT(thisObject); >+ FALLTHROUGH; >+ case JSC::JSCCallbackFunction::Type::Function: >+ return JSObjectCallAsFunction(jsContext, function, thisObject, arguments.size(), arguments.data(), exception); >+ break; >+ } >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ > static GRefPtr<JSCValue> jscValueCallFunction(JSCValue* value, JSObjectRef function, JSC::JSCCallbackFunction::Type functionType, JSObjectRef thisObject, GType firstParameterType, va_list args) > { > JSCValuePrivate* priv = value->priv; >@@ -858,18 +874,7 @@ static GRefPtr<JSCValue> jscValueCallFunction(JSCValue* value, JSObjectRef funct > parameterType = va_arg(args, GType); > } > >- JSValueRef result; >- switch (functionType) { >- case JSC::JSCCallbackFunction::Type::Constructor: >- result = JSObjectCallAsConstructor(jsContext, function, arguments.size(), arguments.data(), &exception); >- break; >- case JSC::JSCCallbackFunction::Type::Method: >- ASSERT(thisObject); >- FALLTHROUGH; >- case JSC::JSCCallbackFunction::Type::Function: >- result = JSObjectCallAsFunction(jsContext, function, thisObject, arguments.size(), arguments.data(), &exception); >- break; >- } >+ auto result = jsObjectCall(jsContext, function, functionType, thisObject, arguments, &exception); > if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) > return adoptGRef(jsc_value_new_undefined(priv->context.get())); > >@@ -877,7 +882,7 @@ static GRefPtr<JSCValue> jscValueCallFunction(JSCValue* value, JSObjectRef funct > } > > /** >- * jsc_value_object_invoke_method: >+ * jsc_value_object_invoke_method: (skip) > * @value: a #JSCValue > * @name: the method name > * @first_parameter_type: #GType of first parameter, or %G_TYPE_NONE >@@ -923,6 +928,60 @@ JSCValue* jsc_value_object_invoke_method(JSCValue* value, const char* name, GTyp > return result.leakRef(); > } > >+/** >+ * jsc_value_object_invoke_methodv: (rename-to jsc_value_object_invoke_method) >+ * @value: a #JSCValue >+ * @name: the method name >+ * @n_parameters: the number of parameters >+ * @parameters: (nullable) (array length=n_parameters) (element-type JSCValue): the #JSCValue<!-- -->s to pass as parameters to the method, or %NULL >+ * >+ * Invoke method with @name on object referenced by @value, passing the given @parameters. If >+ * @n_parameters is 0 no parameters will be passed to the method. >+ * The object instance will be handled automatically even when the method is a custom one >+ * registered with jsc_class_add_method(), so it should never be passed explicitly as parameter >+ * of this function. >+ * >+ * This function always returns a #JSCValue, in case of void methods a #JSCValue referencing >+ * <function>undefined</function> is returned. >+ * >+ * Returns: (transfer full): a #JSCValue with the return value of the method. >+ */ >+JSCValue* jsc_value_object_invoke_methodv(JSCValue* value, const char* name, unsigned parametersCount, JSCValue** parameters) >+{ >+ g_return_val_if_fail(JSC_IS_VALUE(value), nullptr); >+ g_return_val_if_fail(name, nullptr); >+ g_return_val_if_fail(!parametersCount || parameters, nullptr); >+ >+ JSCValuePrivate* priv = value->priv; >+ auto* jsContext = jscContextGetJSContext(priv->context.get()); >+ JSValueRef exception = nullptr; >+ JSObjectRef object = JSValueToObject(jsContext, priv->jsValue, &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ return jsc_value_new_undefined(priv->context.get()); >+ >+ JSRetainPtr<JSStringRef> methodName(Adopt, JSStringCreateWithUTF8CString(name)); >+ JSValueRef functionValue = JSObjectGetProperty(jsContext, object, methodName.get(), &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ return jsc_value_new_undefined(priv->context.get()); >+ >+ JSObjectRef function = JSValueToObject(jsContext, functionValue, &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ return jsc_value_new_undefined(priv->context.get()); >+ >+ Vector<JSValueRef> arguments; >+ if (parametersCount) { >+ arguments.reserveInitialCapacity(parametersCount); >+ for (unsigned i = 0; i < parametersCount; ++i) >+ arguments.uncheckedAppend(jscValueGetJSValue(parameters[i])); >+ } >+ >+ auto result = jsObjectCall(jsContext, function, JSC::JSCCallbackFunction::Type::Method, object, arguments, &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ jsc_value_new_undefined(priv->context.get()); >+ >+ return jscContextGetOrCreateValue(priv->context.get(), result).leakRef(); >+} >+ > /** > * JSCValuePropertyFlags: > * @JSC_VALUE_PROPERTY_CONFIGURABLE: the type of the property descriptor may be changed and the >@@ -1021,8 +1080,19 @@ void jsc_value_object_define_property_accessor(JSCValue* value, const char* prop > 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) >+{ >+ GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify)))); >+ JSC::ExecState* exec = toJS(jscContextGetJSContext(context)); >+ JSC::VM& vm = exec->vm(); >+ JSC::JSLockHolder locker(vm); >+ auto* functionObject = toRef(JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), name ? String::fromUTF8(name) : ASCIILiteral("anonymous"), >+ JSC::JSCCallbackFunction::Type::Function, nullptr, WTFMove(closure), returnType, WTFMove(parameters))); >+ return jscContextGetOrCreateValue(context, functionObject); >+} >+ > /** >- * jsc_value_new_function: >+ * jsc_value_new_function: (skip) > * @context: a #JSCContext: > * @name: (nullable): the function name or %NULL > * @callback: (scope async): a #GCallback. >@@ -1054,13 +1124,41 @@ JSCValue* jsc_value_new_function(JSCContext* context, const char* name, GCallbac > } > va_end(args); > >- GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(callback, userData, reinterpret_cast<GClosureNotify>(reinterpret_cast<GCallback>(destroyNotify)))); >- JSC::ExecState* exec = toJS(jscContextGetJSContext(context)); >- JSC::VM& vm = exec->vm(); >- JSC::JSLockHolder locker(vm); >- auto* functionObject = toRef(JSC::JSCCallbackFunction::create(vm, exec->lexicalGlobalObject(), name ? String::fromUTF8(name) : ASCIILiteral("anonymous"), >- JSC::JSCCallbackFunction::Type::Function, nullptr, WTFMove(closure), returnType, WTFMove(parameters))); >- return jscContextGetOrCreateValue(context, functionObject).leakRef(); >+ return jscValueFunctionCreate(context, name, callback, userData, destroyNotify, returnType, WTFMove(parameters)).leakRef(); >+} >+ >+/** >+ * jsc_value_new_functionv: (rename-to jsc_value_new_function) >+ * @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. >+ * @n_parameters: the number of parameters >+ * @parameter_types: (nullable) (array length=n_parameters) (element-type GType): a list of #GType<!-- -->s, one for each parameter, or %NULL >+ * >+ * 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 the function parameters 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_functionv(JSCContext* context, const char* name, GCallback callback, gpointer userData, GDestroyNotify destroyNotify, GType returnType, unsigned parametersCount, GType *parameterTypes) >+{ >+ g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr); >+ g_return_val_if_fail(callback, nullptr); >+ g_return_val_if_fail(!parametersCount || parameterTypes, nullptr); >+ >+ Vector<GType> parameters; >+ if (parametersCount) { >+ parameters.reserveInitialCapacity(parametersCount); >+ for (unsigned i = 0; i < parametersCount; ++i) >+ parameters.uncheckedAppend(parameterTypes[i]); >+ } >+ >+ return jscValueFunctionCreate(context, name, callback, userData, destroyNotify, returnType, WTFMove(parameters)).leakRef(); > } > > /** >@@ -1083,7 +1181,7 @@ gboolean jsc_value_is_function(JSCValue* value) > } > > /** >- * jsc_value_function_call: >+ * jsc_value_function_call: (skip) > * @value: a #JSCValue > * @first_parameter_type: #GType of first parameter, or %G_TYPE_NONE > * @...: value of the first parameter, followed optionally by more type/value pairs, followed by %G_TYPE_NONE >@@ -1115,6 +1213,46 @@ JSCValue* jsc_value_function_call(JSCValue* value, GType firstParameterType, ... > return result.leakRef(); > } > >+/** >+ * jsc_value_function_callv: (rename-to jsc_value_function_call) >+ * @value: a #JSCValue >+ * @n_parameters: the number of parameters >+ * @parameters: (nullable) (array length=n_parameters) (element-type JSCValue): the #JSCValue<!-- -->s to pass as parameters to the function, or %NULL >+ * >+ * Call function referenced by @value, passing the given @parameters. If @n_parameters >+ * is 0 no parameters will be passed to the function. >+ * >+ * This function always returns a #JSCValue, in case of void functions a #JSCValue referencing >+ * <function>undefined</function> is returned >+ * >+ * Returns: (transfer full): a #JSCValue with the return value of the function. >+ */ >+JSCValue* jsc_value_function_callv(JSCValue* value, unsigned parametersCount, JSCValue** parameters) >+{ >+ g_return_val_if_fail(JSC_IS_VALUE(value), nullptr); >+ g_return_val_if_fail(!parametersCount || parameters, nullptr); >+ >+ JSCValuePrivate* priv = value->priv; >+ auto* jsContext = jscContextGetJSContext(priv->context.get()); >+ JSValueRef exception = nullptr; >+ JSObjectRef function = JSValueToObject(jsContext, priv->jsValue, &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ return jsc_value_new_undefined(priv->context.get()); >+ >+ Vector<JSValueRef> arguments; >+ if (parametersCount) { >+ arguments.reserveInitialCapacity(parametersCount); >+ for (unsigned i = 0; i < parametersCount; ++i) >+ arguments.uncheckedAppend(jscValueGetJSValue(parameters[i])); >+ } >+ >+ auto result = jsObjectCall(jsContext, function, JSC::JSCCallbackFunction::Type::Function, nullptr, arguments, &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ return jsc_value_new_undefined(priv->context.get()); >+ >+ return jscContextGetOrCreateValue(priv->context.get(), result).leakRef(); >+} >+ > /** > * jsc_value_is_constructor: > * @value: a #JSCValue >@@ -1135,7 +1273,7 @@ gboolean jsc_value_is_constructor(JSCValue* value) > } > > /** >- * jsc_value_constructor_call: >+ * jsc_value_constructor_call: (skip) > * @value: a #JSCValue > * @first_parameter_type: #GType of first parameter, or %G_TYPE_NONE > * @...: value of the first parameter, followed optionally by more type/value pairs, followed by %G_TYPE_NONE >@@ -1163,3 +1301,40 @@ JSCValue* jsc_value_constructor_call(JSCValue* value, GType firstParameterType, > > return result.leakRef(); > } >+ >+/** >+ * jsc_value_constructor_callv: (rename-to jsc_value_constructor_call) >+ * @value: a #JSCValue >+ * @n_parameters: the number of parameters >+ * @parameters: (nullable) (array length=n_parameters) (element-type JSCValue): the #JSCValue<!-- -->s to pass as parameters to the constructor, or %NULL >+ * >+ * Invoke <function>new</function> with constructor referenced by @value. If @n_parameters >+ * is 0 no parameters will be passed to the constructor. >+ * >+ * Returns: (transfer full): a #JSCValue referencing the newly created object instance. >+ */ >+JSCValue* jsc_value_constructor_callv(JSCValue* value, unsigned parametersCount, JSCValue** parameters) >+{ >+ g_return_val_if_fail(JSC_IS_VALUE(value), nullptr); >+ g_return_val_if_fail(!parametersCount || parameters, nullptr); >+ >+ JSCValuePrivate* priv = value->priv; >+ auto* jsContext = jscContextGetJSContext(priv->context.get()); >+ JSValueRef exception = nullptr; >+ JSObjectRef function = JSValueToObject(jsContext, priv->jsValue, &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ return jsc_value_new_undefined(priv->context.get()); >+ >+ Vector<JSValueRef> arguments; >+ if (parametersCount) { >+ arguments.reserveInitialCapacity(parametersCount); >+ for (unsigned i = 0; i < parametersCount; ++i) >+ arguments.uncheckedAppend(jscValueGetJSValue(parameters[i])); >+ } >+ >+ auto result = jsObjectCall(jsContext, function, JSC::JSCCallbackFunction::Type::Constructor, nullptr, arguments, &exception); >+ if (jscContextHandleExceptionIfNeeded(priv->context.get(), exception)) >+ return jsc_value_new_undefined(priv->context.get()); >+ >+ return jscContextGetOrCreateValue(priv->context.get(), result).leakRef(); >+} >diff --git a/Source/JavaScriptCore/API/glib/JSCValue.h b/Source/JavaScriptCore/API/glib/JSCValue.h >index fb79f016c70..26550ab6445 100644 >--- a/Source/JavaScriptCore/API/glib/JSCValue.h >+++ b/Source/JavaScriptCore/API/glib/JSCValue.h >@@ -180,6 +180,12 @@ jsc_value_object_invoke_method (JSCValue *value, > GType first_parameter_type, > ...); > >+JSC_API JSCValue * >+jsc_value_object_invoke_methodv (JSCValue *value, >+ const char *name, >+ guint n_parameters, >+ JSCValue **parameters); >+ > JSC_API void > jsc_value_object_define_property_data (JSCValue *value, > const char *property_name, >@@ -206,6 +212,16 @@ jsc_value_new_function (JSCContext *context, > guint n_params, > ...); > >+JSC_API JSCValue * >+jsc_value_new_functionv (JSCContext *context, >+ const char *name, >+ GCallback callback, >+ gpointer user_data, >+ GDestroyNotify destroy_notify, >+ GType return_type, >+ guint n_parameters, >+ GType *parameter_types); >+ > JSC_API gboolean > jsc_value_is_function (JSCValue *value); > >@@ -214,6 +230,11 @@ jsc_value_function_call (JSCValue *value, > GType first_parameter_type, > ...); > >+JSC_API JSCValue * >+jsc_value_function_callv (JSCValue *value, >+ guint n_parameters, >+ JSCValue **parameters); >+ > JSC_API gboolean > jsc_value_is_constructor (JSCValue *value); > >@@ -222,6 +243,11 @@ jsc_value_constructor_call (JSCValue *value, > GType first_parameter_type, > ...); > >+JSC_API JSCValue * >+jsc_value_constructor_callv (JSCValue *value, >+ guint n_parameters, >+ JSCValue **parameters); >+ > G_END_DECLS > > #endif /* JSCValue_h */ >diff --git a/Source/JavaScriptCore/API/glib/docs/jsc-glib-4.0-sections.txt b/Source/JavaScriptCore/API/glib/docs/jsc-glib-4.0-sections.txt >index e6244e88f57..8755b6e4a8a 100644 >--- a/Source/JavaScriptCore/API/glib/docs/jsc-glib-4.0-sections.txt >+++ b/Source/JavaScriptCore/API/glib/docs/jsc-glib-4.0-sections.txt >@@ -92,13 +92,17 @@ jsc_value_object_has_property > jsc_value_object_delete_property > jsc_value_object_enumerate_properties > jsc_value_object_invoke_method >+jsc_value_object_invoke_methodv > jsc_value_object_define_property_data > jsc_value_object_define_property_accessor > jsc_value_new_function >+jsc_value_new_functionv > jsc_value_is_function > jsc_value_function_call >+jsc_value_function_callv > jsc_value_is_constructor > jsc_value_constructor_call >+jsc_value_constructor_callv > > <SUBSECTION Standard> > JSCValueClass >@@ -171,7 +175,9 @@ JSCClassVTable > jsc_class_get_name > jsc_class_get_parent > jsc_class_add_constructor >+jsc_class_add_constructorv > jsc_class_add_method >+jsc_class_add_methodv > jsc_class_add_property > > <SUBSECTION Standard> >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 377da691408..1678f8cbe39 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,30 @@ >+2018-05-10 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ [JSC][GLIB] Add introspectable alternatives to functions using vargars >+ https://bugs.webkit.org/show_bug.cgi?id=185508 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * API/glib/JSCClass.cpp: >+ (jscClassCreateConstructor): >+ (jsc_class_add_constructor): >+ (jsc_class_add_constructorv): >+ (jscClassAddMethod): >+ (jsc_class_add_method): >+ (jsc_class_add_methodv): >+ * API/glib/JSCClass.h: >+ * API/glib/JSCValue.cpp: >+ (jsObjectCall): >+ (jscValueCallFunction): >+ (jsc_value_object_invoke_methodv): >+ (jscValueFunctionCreate): >+ (jsc_value_new_function): >+ (jsc_value_new_functionv): >+ (jsc_value_function_callv): >+ (jsc_value_constructor_callv): >+ * API/glib/JSCValue.h: >+ * API/glib/docs/jsc-glib-4.0-sections.txt: >+ > 2018-05-09 Caio Lima <ticaiolima@gmail.com> > > [ESNext][BigInt] Implement support for "==" operation >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index d29b9828afa..282288e1cc4 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,16 @@ >+2018-05-10 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ [JSC][GLIB] Add introspectable alternatives to functions using vargars >+ https://bugs.webkit.org/show_bug.cgi?id=185508 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add test cases for the new API. >+ >+ * TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp: >+ (testJSCFunction): >+ (testJSCObject): >+ > 2018-05-10 Carlos Garcia Campos <cgarcia@igalia.com> > > [GTK] Add support for settings cookies policy and storage type in MiniBrowser >diff --git a/Tools/TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp b/Tools/TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp >index a88ee98eaa1..2db1af87a2f 100644 >--- a/Tools/TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp >+++ b/Tools/TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp >@@ -581,6 +581,42 @@ static void testJSCFunction() > GRefPtr<JSCValue> value = adoptGRef(jsc_value_function_call(function.get(), G_TYPE_INT, 200, G_TYPE_NONE)); > checker.watch(value.get()); > g_assert_true(value.get() == result.get()); >+ >+ GRefPtr<GPtrArray> parameters = adoptGRef(g_ptr_array_new_with_free_func(g_object_unref)); >+ auto* parameter = jsc_value_new_number(context.get(), 200); >+ checker.watch(parameter); >+ g_ptr_array_add(parameters.get(), parameter); >+ value = adoptGRef(jsc_value_function_callv(function.get(), parameters->len, reinterpret_cast<JSCValue**>(parameters->pdata))); >+ checker.watch(value.get()); >+ g_assert_true(value.get() == result.get()); >+ } >+ >+ { >+ LeakChecker checker; >+ GRefPtr<JSCContext> context = adoptGRef(jsc_context_new()); >+ checker.watch(context.get()); >+ ExceptionHandler exceptionHandler(context.get()); >+ >+ GType parameterTypes[] = { G_TYPE_INT }; >+ GRefPtr<JSCValue> function = adoptGRef(jsc_value_new_functionv(context.get(), "foo", G_CALLBACK(foo), nullptr, nullptr, G_TYPE_INT, 1, parameterTypes)); >+ checker.watch(function.get()); >+ jsc_context_set_value(context.get(), "foo", function.get()); >+ GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate(context.get(), "foo(200)", -1)); >+ checker.watch(result.get()); >+ g_assert_true(jsc_value_is_number(result.get())); >+ g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 400); >+ >+ GRefPtr<JSCValue> value = adoptGRef(jsc_value_function_call(function.get(), G_TYPE_INT, 200, G_TYPE_NONE)); >+ checker.watch(value.get()); >+ g_assert_true(value.get() == result.get()); >+ >+ GRefPtr<GPtrArray> parameters = adoptGRef(g_ptr_array_new_with_free_func(g_object_unref)); >+ auto* parameter = jsc_value_new_number(context.get(), 200); >+ checker.watch(parameter); >+ g_ptr_array_add(parameters.get(), parameter); >+ value = adoptGRef(jsc_value_function_callv(function.get(), parameters->len, reinterpret_cast<JSCValue**>(parameters->pdata))); >+ checker.watch(value.get()); >+ g_assert_true(value.get() == result.get()); > } > > { >@@ -600,6 +636,14 @@ static void testJSCFunction() > GRefPtr<JSCValue> value = adoptGRef(jsc_value_function_call(function.get(), G_TYPE_INT, 200, G_TYPE_NONE)); > checker.watch(value.get()); > g_assert_true(value.get() == result.get()); >+ >+ GRefPtr<GPtrArray> parameters = adoptGRef(g_ptr_array_new_with_free_func(g_object_unref)); >+ auto* parameter = jsc_value_new_number(context.get(), 200); >+ checker.watch(parameter); >+ g_ptr_array_add(parameters.get(), parameter); >+ value = adoptGRef(jsc_value_function_callv(function.get(), parameters->len, reinterpret_cast<JSCValue**>(parameters->pdata))); >+ checker.watch(value.get()); >+ g_assert_true(value.get() == result.get()); > } > > { >@@ -631,6 +675,15 @@ static void testJSCFunction() > checker.watch(result.get()); > g_assert_true(jsc_value_is_number(result.get())); > g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 400); >+ >+ GRefPtr<GPtrArray> parameters = adoptGRef(g_ptr_array_new()); >+ g_ptr_array_add(parameters.get(), dbl.get()); >+ value = adoptGRef(jsc_value_function_callv(function.get(), parameters->len, reinterpret_cast<JSCValue**>(parameters->pdata))); >+ checker.watch(value.get()); >+ result = adoptGRef(jsc_context_evaluate(context.get(), "result", -1)); >+ checker.watch(result.get()); >+ g_assert_true(jsc_value_is_number(result.get())); >+ g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 400); > } > > { >@@ -715,6 +768,15 @@ static void testJSCObject() > g_assert_true(jsc_value_is_number(result.get())); > g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 400); > >+ GRefPtr<GPtrArray> parameters = adoptGRef(g_ptr_array_new_with_free_func(g_object_unref)); >+ auto* parameter = jsc_value_new_number(context.get(), 200); >+ checker.watch(parameter); >+ g_ptr_array_add(parameters.get(), parameter); >+ result = adoptGRef(jsc_value_object_invoke_methodv(foo.get(), "foo", parameters->len, reinterpret_cast<JSCValue**>(parameters->pdata))); >+ checker.watch(result.get()); >+ g_assert_true(jsc_value_is_number(result.get())); >+ g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 400); >+ > g_assert_false(jsc_value_object_has_property(foo.get(), "bar")); > bool didThrow = false; > g_assert_throw_begin(exceptionHandler, didThrow); >@@ -723,6 +785,12 @@ static void testJSCObject() > g_assert_true(jsc_value_is_undefined(result.get())); > g_assert_did_throw(exceptionHandler, didThrow); > >+ g_assert_throw_begin(exceptionHandler, didThrow); >+ result = adoptGRef(jsc_value_object_invoke_methodv(foo.get(), "bar", parameters->len, reinterpret_cast<JSCValue**>(parameters->pdata))); >+ checker.watch(result.get()); >+ g_assert_true(jsc_value_is_undefined(result.get())); >+ g_assert_did_throw(exceptionHandler, didThrow); >+ > GRefPtr<JSCValue> constructor = adoptGRef(jsc_context_evaluate(context.get(), "Foo", -1)); > checker.watch(constructor.get()); > g_assert_true(jsc_value_is_constructor(constructor.get())); >@@ -747,6 +815,12 @@ static void testJSCObject() > checker.watch(result.get()); > g_assert_true(jsc_value_is_number(result.get())); > g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 1000); >+ >+ GRefPtr<JSCValue> foo2 = adoptGRef(jsc_value_constructor_callv(constructor.get(), 0, nullptr)); >+ checker.watch(foo2.get()); >+ g_assert_true(jsc_value_is_object(foo2.get())); >+ g_assert_true(jsc_value_object_is_instance_of(foo2.get(), "Foo")); >+ g_assert_false(foo.get() == foo2.get()); > } > > { >@@ -1182,12 +1256,18 @@ static void testJSCClass() > g_assert_true(jsc_value_is_number(value.get())); > g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 0); > >+ value = adoptGRef(jsc_value_object_invoke_methodv(foo.get(), "getFoo", 0, nullptr)); >+ checker.watch(value.get()); >+ g_assert_true(jsc_value_is_number(value.get())); >+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 0); >+ > GRefPtr<JSCValue> value2 = adoptGRef(jsc_context_evaluate(context.get(), "f.getFoo()", -1)); > checker.watch(value2.get()); > g_assert_true(value.get() == value2.get()); > > g_assert_false(jsc_value_object_has_property(foo.get(), "setFoo")); >- jsc_class_add_method(jscClass, "setFoo", G_CALLBACK(setFoo), nullptr, nullptr, G_TYPE_NONE, 1, G_TYPE_INT); >+ GType parameterTypes[] = { G_TYPE_INT }; >+ jsc_class_add_methodv(jscClass, "setFoo", G_CALLBACK(setFoo), nullptr, nullptr, G_TYPE_NONE, 1, parameterTypes); > g_assert_true(jsc_value_object_has_property(foo.get(), "setFoo")); > properties.reset(jsc_value_object_enumerate_properties(foo.get())); > g_assert_null(properties.get()); >@@ -1205,7 +1285,12 @@ static void testJSCClass() > g_assert_true(jsc_value_is_number(value.get())); > g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 45); > >- GRefPtr<JSCValue> constructor2 = adoptGRef(jsc_class_add_constructor(jscClass, "CreateWithFoo", G_CALLBACK(fooCreateWithFoo), nullptr, nullptr, G_TYPE_POINTER, 1, G_TYPE_INT)); >+ value = adoptGRef(jsc_value_object_invoke_methodv(foo.get(), "getFoo", 0, nullptr)); >+ checker.watch(value.get()); >+ g_assert_true(jsc_value_is_number(value.get())); >+ g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 45); >+ >+ 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())); > jsc_value_object_set_property(constructor.get(), "CreateWithFoo", constructor2.get()); >@@ -1311,7 +1396,7 @@ static void testJSCClass() > JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); > checker.watch(jscClass); > >- GRefPtr<JSCValue> constructor = adoptGRef(jsc_class_add_constructor(jscClass, nullptr, G_CALLBACK(fooCreate), nullptr, nullptr, G_TYPE_POINTER, 0, G_TYPE_NONE)); >+ GRefPtr<JSCValue> constructor = adoptGRef(jsc_class_add_constructorv(jscClass, nullptr, G_CALLBACK(fooCreate), nullptr, nullptr, G_TYPE_POINTER, 0, nullptr)); > checker.watch(constructor.get()); > g_assert_true(jsc_value_is_constructor(constructor.get())); > jsc_context_set_value(context.get(), jsc_class_get_name(jscClass), constructor.get()); >@@ -1554,7 +1639,12 @@ static void testJSCClass() > g_assert_true(jsc_value_is_number(result.get())); > g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 42); > >- GRefPtr<JSCValue> foo3 = adoptGRef(jsc_value_constructor_call(constructor2.get(), G_TYPE_INT, 62, G_TYPE_NONE)); >+ GRefPtr<GPtrArray> parameters = adoptGRef(g_ptr_array_new_with_free_func(g_object_unref)); >+ auto* parameter = jsc_value_new_number(context.get(), 62); >+ checker.watch(parameter); >+ g_ptr_array_add(parameters.get(), parameter); >+ >+ GRefPtr<JSCValue> foo3 = adoptGRef(jsc_value_constructor_callv(constructor2.get(), parameters->len, reinterpret_cast<JSCValue**>(parameters->pdata))); > checker.watch(foo3.get()); > g_assert_true(jsc_value_is_object(foo3.get())); > g_assert_true(jsc_value_object_is_instance_of(foo3.get(), "wk.Foo"));
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
mcatanzaro
:
review+
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185508
: 340080 |
340100