Changeset 230753 in webkit
- Timestamp:
- Apr 17, 2018, 11:51:33 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
-
Source/JavaScriptCore/API/glib/JSCClass.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/API/glib/JSCClass.h (modified) (1 diff)
-
Source/JavaScriptCore/API/glib/JSCClassPrivate.h (modified) (1 diff)
-
Source/JavaScriptCore/API/glib/JSCContext.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/API/glib/JSCContext.h (modified) (1 diff)
-
Source/JavaScriptCore/API/glib/JSCContextPrivate.h (modified) (1 diff)
-
Source/JavaScriptCore/API/glib/JSCWrapperMap.cpp (modified) (1 diff)
-
Source/JavaScriptCore/API/glib/JSCWrapperMap.h (modified) (1 diff)
-
Source/JavaScriptCore/API/glib/docs/jsc-glib-4.0-sections.txt (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp (modified) (22 diffs)
-
Tools/TestWebKitAPI/Tests/WebKitGLib/WebProcessTest.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/glib/JSCClass.cpp
r229798 r230753 21 21 #include "JSCClass.h" 22 22 23 #include "APICast.h" 24 #include "JSAPIWrapperObject.h" 23 25 #include "JSCCallbackFunction.h" 24 26 #include "JSCClassPrivate.h" 25 27 #include "JSCContextPrivate.h" 28 #include "JSCExceptionPrivate.h" 26 29 #include "JSCInlines.h" 27 30 #include "JSCValuePrivate.h" 31 #include "JSCallbackObject.h" 32 #include "JSRetainPtr.h" 28 33 #include <wtf/glib/GUniquePtr.h> 29 34 #include <wtf/glib/WTFGType.h> … … 54 59 CString name; 55 60 JSClassRef jsClass; 61 JSCClassVTable* vtable; 56 62 GDestroyNotify destroyFunction; 57 63 JSCClass* parentClass; … … 71 77 72 78 WEBKIT_DEFINE_TYPE(JSCClass, jsc_class, G_TYPE_OBJECT) 79 80 class VTableExceptionHandler { 81 public: 82 VTableExceptionHandler(JSCContext* context, JSValueRef* exception) 83 : m_context(context) 84 , m_exception(exception) 85 , m_savedException(exception ? jsc_context_get_exception(m_context) : nullptr) 86 { 87 } 88 89 ~VTableExceptionHandler() 90 { 91 if (!m_exception) 92 return; 93 94 auto* exception = jsc_context_get_exception(m_context); 95 if (m_savedException.get() == exception) 96 return; 97 98 *m_exception = jscExceptionGetJSValue(exception); 99 if (m_savedException) 100 jsc_context_throw_exception(m_context, m_savedException.get()); 101 else 102 jsc_context_clear_exception(m_context); 103 } 104 105 private: 106 JSCContext* m_context { nullptr }; 107 JSValueRef* m_exception { nullptr }; 108 GRefPtr<JSCException> m_savedException; 109 }; 110 111 static JSValueRef getProperty(JSContextRef callerContext, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) 112 { 113 JSC::JSLockHolder locker(toJS(callerContext)); 114 auto* jsObject = toJS(object); 115 auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec())); 116 auto* jsContext = jscContextGetJSContext(context.get()); 117 if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm())) 118 return nullptr; 119 120 gpointer instance = jscContextWrappedObject(context.get(), object); 121 if (!instance) 122 return nullptr; 123 124 VTableExceptionHandler exceptionHandler(context.get(), exception); 125 126 JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef(); 127 for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) { 128 if (!jscClass->priv->vtable) 129 continue; 130 131 if (auto* getPropertyFunction = jscClass->priv->vtable->get_property) { 132 if (GRefPtr<JSCValue> value = adoptGRef(getPropertyFunction(jscClass, context.get(), instance, propertyName->string().utf8().data()))) 133 return jscValueGetJSValue(value.get()); 134 } 135 } 136 return nullptr; 137 } 138 139 static bool setProperty(JSContextRef callerContext, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) 140 { 141 JSC::JSLockHolder locker(toJS(callerContext)); 142 auto* jsObject = toJS(object); 143 auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec())); 144 auto* jsContext = jscContextGetJSContext(context.get()); 145 if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm())) 146 return false; 147 148 gpointer instance = jscContextWrappedObject(context.get(), object); 149 if (!instance) 150 return false; 151 152 VTableExceptionHandler exceptionHandler(context.get(), exception); 153 154 GRefPtr<JSCValue> propertyValue; 155 JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef(); 156 for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) { 157 if (!jscClass->priv->vtable) 158 continue; 159 160 if (auto* setPropertyFunction = jscClass->priv->vtable->set_property) { 161 if (!propertyValue) 162 propertyValue = jscContextGetOrCreateValue(context.get(), value); 163 if (setPropertyFunction(jscClass, context.get(), instance, propertyName->string().utf8().data(), propertyValue.get())) 164 return true; 165 } 166 } 167 return false; 168 } 169 170 static bool hasProperty(JSContextRef callerContext, JSObjectRef object, JSStringRef propertyName) 171 { 172 JSC::JSLockHolder locker(toJS(callerContext)); 173 auto* jsObject = toJS(object); 174 auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec())); 175 auto* jsContext = jscContextGetJSContext(context.get()); 176 if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm())) 177 return false; 178 179 gpointer instance = jscContextWrappedObject(context.get(), object); 180 if (!instance) 181 return false; 182 183 JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef(); 184 for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) { 185 if (!jscClass->priv->vtable) 186 continue; 187 188 if (auto* hasPropertyFunction = jscClass->priv->vtable->has_property) { 189 if (hasPropertyFunction(jscClass, context.get(), instance, propertyName->string().utf8().data())) 190 return true; 191 } 192 } 193 194 return false; 195 } 196 197 static bool deleteProperty(JSContextRef callerContext, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) 198 { 199 JSC::JSLockHolder locker(toJS(callerContext)); 200 auto* jsObject = toJS(object); 201 auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec())); 202 auto* jsContext = jscContextGetJSContext(context.get()); 203 if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm())) 204 return false; 205 206 gpointer instance = jscContextWrappedObject(context.get(), object); 207 if (!instance) 208 return false; 209 210 VTableExceptionHandler exceptionHandler(context.get(), exception); 211 212 JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef(); 213 for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) { 214 if (!jscClass->priv->vtable) 215 continue; 216 217 if (auto* deletePropertyFunction = jscClass->priv->vtable->delete_property) { 218 if (deletePropertyFunction(jscClass, context.get(), instance, propertyName->string().utf8().data())) 219 return true; 220 } 221 } 222 return false; 223 } 224 225 static void getPropertyNames(JSContextRef callerContext, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) 226 { 227 JSC::JSLockHolder locker(toJS(callerContext)); 228 auto* jsObject = toJS(object); 229 auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec())); 230 auto* jsContext = jscContextGetJSContext(context.get()); 231 if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm())) 232 return; 233 234 gpointer instance = jscContextWrappedObject(context.get(), object); 235 if (!instance) 236 return; 237 238 JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef(); 239 for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) { 240 if (!jscClass->priv->vtable) 241 continue; 242 243 if (auto* enumeratePropertiesFunction = jscClass->priv->vtable->enumerate_properties) { 244 GUniquePtr<char*> properties(enumeratePropertiesFunction(jscClass, context.get(), instance)); 245 if (properties) { 246 unsigned i = 0; 247 while (const auto* name = properties.get()[i++]) { 248 JSRetainPtr<JSStringRef> propertyName(Adopt, JSStringCreateWithUTF8CString(name)); 249 JSPropertyNameAccumulatorAddName(propertyNames, propertyName.get()); 250 } 251 } 252 } 253 } 254 } 73 255 74 256 static void jscClassGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* paramSpec) … … 122 304 } 123 305 124 static void jscClassConstructed(GObject* object)125 {126 G_OBJECT_CLASS(jsc_class_parent_class)->constructed(object);127 128 JSCClassPrivate* priv = JSC_CLASS(object)->priv;129 JSClassDefinition definition = kJSClassDefinitionEmpty;130 definition.className = priv->name.data();131 priv->jsClass = JSClassCreate(&definition);132 133 GUniquePtr<char> prototypeName(g_strdup_printf("%sPrototype", priv->name.data()));134 JSClassDefinition prototypeDefinition = kJSClassDefinitionEmpty;135 prototypeDefinition.className = prototypeName.get();136 JSClassRef prototypeClass = JSClassCreate(&prototypeDefinition);137 priv->prototype = jscContextGetOrCreateJSWrapper(priv->context, prototypeClass);138 JSClassRelease(prototypeClass);139 140 if (priv->parentClass)141 JSObjectSetPrototype(jscContextGetJSContext(priv->context), toRef(priv->prototype.get()), toRef(priv->parentClass->priv->prototype.get()));142 }143 144 306 static void jsc_class_class_init(JSCClassClass* klass) 145 307 { 146 308 GObjectClass* objClass = G_OBJECT_CLASS(klass); 147 objClass->constructed = jscClassConstructed;148 309 objClass->dispose = jscClassDispose; 149 310 objClass->get_property = jscClassGetProperty; … … 193 354 } 194 355 195 GRefPtr<JSCClass> jscClassCreate(JSCContext* context, const char* name, JSCClass* parentClass, GDestroyNotify destroyFunction) 356 /** 357 * JSCClassGetPropertyFunction: 358 * @jsc_class: a #JSCClass 359 * @context: a #JSCContext 360 * @instance: the @jsc_class instance 361 * @name: the property name 362 * 363 * The type of get_property in #JSCClassVTable. This is only required when you need to handle 364 * external properties not added to the prototype. 365 * 366 * Returns: (transfer full) (nullable): a #JSCValue or %NULL to forward the request to 367 * the parent class or prototype chain 368 */ 369 370 /** 371 * JSCClassSetPropertyFunction: 372 * @jsc_class: a #JSCClass 373 * @context: a #JSCContext 374 * @instance: the @jsc_class instance 375 * @name: the property name 376 * @value: the #JSCValue to set 377 * 378 * The type of set_property in #JSCClassVTable. This is only required when you need to handle 379 * external properties not added to the prototype. 380 * 381 * Returns: %TRUE if handled or %FALSE to forward the request to the parent class or prototype chain. 382 */ 383 384 /** 385 * JSCClassHasPropertyFunction: 386 * @jsc_class: a #JSCClass 387 * @context: a #JSCContext 388 * @instance: the @jsc_class instance 389 * @name: the property name 390 * 391 * The type of has_property in #JSCClassVTable. This is only required when you need to handle 392 * external properties not added to the prototype. 393 * 394 * Returns: %TRUE if @instance has a property with @name or %FALSE to forward the request 395 * to the parent class or prototype chain. 396 */ 397 398 /** 399 * JSCClassDeletePropertyFunction: 400 * @jsc_class: a #JSCClass 401 * @context: a #JSCContext 402 * @instance: the @jsc_class instance 403 * @name: the property name 404 * 405 * The type of delete_property in #JSCClassVTable. This is only required when you need to handle 406 * external properties not added to the prototype. 407 * 408 * Returns: %TRUE if handled or %FALSE to to forward the request to the parent class or prototype chain. 409 */ 410 411 /** 412 * JSCClassEnumeratePropertiesFunction: 413 * @jsc_class: a #JSCClass 414 * @context: a #JSCContext 415 * @instance: the @jsc_class instance 416 * 417 * The type of enumerate_properties in #JSCClassVTable. This is only required when you need to handle 418 * external properties not added to the prototype. 419 * 420 * Returns: (array zero-terminated=1) (transfer full) (nullable): a %NULL-terminated array of strings 421 * containing the property names, or %NULL if @instance doesn't have enumerable properties. 422 */ 423 424 /** 425 * JSCClassVTable: 426 * @get_property: a #JSCClassGetPropertyFunction for getting a property. 427 * @set_property: a #JSCClassSetPropertyFunction for setting a property. 428 * @has_property: a #JSCClassHasPropertyFunction for querying a property. 429 * @delete_property: a #JSCClassDeletePropertyFunction for deleting a property. 430 * @enumerate_properties: a #JSCClassEnumeratePropertiesFunction for enumerating properties. 431 * 432 * Virtual table for a JSCClass. This can be optionally used when registering a #JSCClass in a #JSCContext 433 * to provide a custom implementation for the class. All virtual functions are optional and can be set to 434 * %NULL to fallback to the default implementation. 435 */ 436 437 GRefPtr<JSCClass> jscClassCreate(JSCContext* context, const char* name, JSCClass* parentClass, JSCClassVTable* vtable, GDestroyNotify destroyFunction) 196 438 { 197 439 GRefPtr<JSCClass> jscClass = adoptGRef(JSC_CLASS(g_object_new(JSC_TYPE_CLASS, "context", context, "name", name, "parent", parentClass, nullptr))); 198 jscClass->priv->destroyFunction = destroyFunction; 440 441 JSCClassPrivate* priv = jscClass->priv; 442 priv->vtable = vtable; 443 priv->destroyFunction = destroyFunction; 444 445 JSClassDefinition definition = kJSClassDefinitionEmpty; 446 definition.className = priv->name.data(); 447 448 #define SET_IMPL_IF_NEEDED(definitionFunc, vtableFunc) \ 449 for (auto* klass = jscClass.get(); klass; klass = klass->priv->parentClass) { \ 450 if (klass->priv->vtable && klass->priv->vtable->vtableFunc) { \ 451 definition.definitionFunc = definitionFunc; \ 452 break; \ 453 } \ 454 } 455 456 SET_IMPL_IF_NEEDED(getProperty, get_property); 457 SET_IMPL_IF_NEEDED(setProperty, set_property); 458 SET_IMPL_IF_NEEDED(hasProperty, has_property); 459 SET_IMPL_IF_NEEDED(deleteProperty, delete_property); 460 SET_IMPL_IF_NEEDED(getPropertyNames, enumerate_properties); 461 462 #undef SET_IMPL_IF_NEEDED 463 464 priv->jsClass = JSClassCreate(&definition); 465 466 GUniquePtr<char> prototypeName(g_strdup_printf("%sPrototype", priv->name.data())); 467 JSClassDefinition prototypeDefinition = kJSClassDefinitionEmpty; 468 prototypeDefinition.className = prototypeName.get(); 469 JSClassRef prototypeClass = JSClassCreate(&prototypeDefinition); 470 priv->prototype = jscContextGetOrCreateJSWrapper(priv->context, prototypeClass); 471 JSClassRelease(prototypeClass); 472 473 if (priv->parentClass) 474 JSObjectSetPrototype(jscContextGetJSContext(priv->context), toRef(priv->prototype.get()), toRef(priv->parentClass->priv->prototype.get())); 199 475 return jscClass; 200 476 } -
trunk/Source/JavaScriptCore/API/glib/JSCClass.h
r229799 r230753 39 39 40 40 typedef struct _JSCContext JSCContext; 41 42 typedef JSCValue *(*JSCClassGetPropertyFunction) (JSCClass *jsc_class, 43 JSCContext *context, 44 gpointer instance, 45 const char *name); 46 typedef gboolean (*JSCClassSetPropertyFunction) (JSCClass *jsc_class, 47 JSCContext *context, 48 gpointer instance, 49 const char *name, 50 JSCValue *value); 51 typedef gboolean (*JSCClassHasPropertyFunction) (JSCClass *jsc_class, 52 JSCContext *context, 53 gpointer instance, 54 const char *name); 55 typedef gboolean (*JSCClassDeletePropertyFunction) (JSCClass *jsc_class, 56 JSCContext *context, 57 gpointer instance, 58 const char *name); 59 typedef gchar **(*JSCClassEnumeratePropertiesFunction) (JSCClass *jsc_class, 60 JSCContext *context, 61 gpointer instance); 62 63 64 typedef struct { 65 JSCClassGetPropertyFunction get_property; 66 JSCClassSetPropertyFunction set_property; 67 JSCClassHasPropertyFunction has_property; 68 JSCClassDeletePropertyFunction delete_property; 69 JSCClassEnumeratePropertiesFunction enumerate_properties; 70 71 /*< private >*/ 72 void (*_jsc_reserved0) (void); 73 void (*_jsc_reserved1) (void); 74 void (*_jsc_reserved2) (void); 75 void (*_jsc_reserved3) (void); 76 } JSCClassVTable; 41 77 42 78 JSC_API GType -
trunk/Source/JavaScriptCore/API/glib/JSCClassPrivate.h
r229798 r230753 26 26 #include <wtf/glib/GRefPtr.h> 27 27 28 GRefPtr<JSCClass> jscClassCreate(JSCContext*, const char*, JSCClass*, GDestroyNotify);28 GRefPtr<JSCClass> jscClassCreate(JSCContext*, const char*, JSCClass*, JSCClassVTable*, GDestroyNotify); 29 29 JSClassRef jscClassGetJSClass(JSCClass*); 30 30 JSC::JSObject* jscClassGetOrCreateJSWrapper(JSCClass*, gpointer); -
trunk/Source/JavaScriptCore/API/glib/JSCContext.cpp
r230705 r230753 239 239 { 240 240 return wrapperMap(context).wrappedObject(context->priv->jsContext.get(), jsObject); 241 } 242 243 JSCClass* jscContextGetRegisteredClass(JSCContext* context, JSClassRef jsClass) 244 { 245 return wrapperMap(context).registeredClass(jsClass); 241 246 } 242 247 … … 763 768 * @context: a #JSCContext 764 769 * @name: the class name 765 * @parent_class: (nullable): a #JSCClass 770 * @parent_class: (nullable): a #JSCClass or %NULL 771 * @vtable: (nullable): an optional #JSCClassVTable or %NULL 766 772 * @destroy_notify: (nullable): a destroy notifier for class instances 767 773 * 768 774 * Register a custom class in @context using the given @name. If the new class inherits from 769 775 * another #JSCClass, the parent should be passed as @parent_class, otherwise %NULL should be 770 * used. When an instance of the #JSCClass is cleared in the context, @destroy_notify is 771 * called with the instance as parameter. 776 * used. The optional @vtable parameter allows to provide a custom implementation for handling 777 * the class, for example, to handle external properties not added to the prototype. 778 * When an instance of the #JSCClass is cleared in the context, @destroy_notify is called with 779 * the instance as parameter. 772 780 * 773 781 * Returns: (transfer none): a #JSCClass 774 782 */ 775 JSCClass* jsc_context_register_class(JSCContext* context, const char* name, JSCClass* parentClass, GDestroyNotify destroyFunction)783 JSCClass* jsc_context_register_class(JSCContext* context, const char* name, JSCClass* parentClass, JSCClassVTable* vtable, GDestroyNotify destroyFunction) 776 784 { 777 785 g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr); … … 779 787 g_return_val_if_fail(!parentClass || JSC_IS_CLASS(parentClass), nullptr); 780 788 781 auto jscClass = jscClassCreate(context, name, parentClass, destroyFunction);789 auto jscClass = jscClassCreate(context, name, parentClass, vtable, destroyFunction); 782 790 wrapperMap(context).registerClass(jscClass.get()); 783 791 return jscClass.get(); -
trunk/Source/JavaScriptCore/API/glib/JSCContext.h
r230705 r230753 127 127 const char *name, 128 128 JSCClass *parent_class, 129 JSCClassVTable *vtable, 129 130 GDestroyNotify destroy_notify); 130 131 -
trunk/Source/JavaScriptCore/API/glib/JSCContextPrivate.h
r229798 r230753 33 33 JSC::JSObject* jscContextGetOrCreateJSWrapper(JSCContext*, JSClassRef, JSValueRef prototype = nullptr, gpointer = nullptr, GDestroyNotify = nullptr); 34 34 gpointer jscContextWrappedObject(JSCContext*, JSObjectRef); 35 JSCClass* jscContextGetRegisteredClass(JSCContext*, JSClassRef); 35 36 36 37 struct CallbackData { -
trunk/Source/JavaScriptCore/API/glib/JSCWrapperMap.cpp
r229800 r230753 69 69 } 70 70 71 JSCClass* WrapperMap::registeredClass(JSClassRef jsClass) const 72 { 73 return m_classMap.get(jsClass); 74 } 75 71 76 JSObject* WrapperMap::createJSWrappper(JSGlobalContextRef jsContext, JSClassRef jsClass, JSValueRef prototype, gpointer wrappedObject, GDestroyNotify destroyFunction) 72 77 { -
trunk/Source/JavaScriptCore/API/glib/JSCWrapperMap.h
r229798 r230753 46 46 47 47 void registerClass(JSCClass*); 48 JSCClass* registeredClass(JSClassRef) const; 48 49 49 50 JSObject* createJSWrappper(JSGlobalContextRef, JSClassRef, JSValueRef prototype, gpointer, GDestroyNotify); -
trunk/Source/JavaScriptCore/API/glib/docs/jsc-glib-4.0-sections.txt
r230705 r230753 163 163 <TITLE>JSCClass</TITLE> 164 164 JSCClass 165 JSCClassGetPropertyFunction 166 JSCClassSetPropertyFunction 167 JSCClassHasPropertyFunction 168 JSCClassDeletePropertyFunction 169 JSCClassEnumeratePropertiesFunction 170 JSCClassVTable 165 171 jsc_class_get_name 166 172 jsc_class_get_parent -
trunk/Source/JavaScriptCore/ChangeLog
r230748 r230753 1 2018-04-17 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GLIB] Make it possible to handle JSCClass external properties not added to the prototype 4 https://bugs.webkit.org/show_bug.cgi?id=184687 5 6 Reviewed by Michael Catanzaro. 7 8 Add JSCClassVTable that can be optionally passed to jsc_context_register_class() to provide implmentations for 9 JSClassDefinition. This is required to implement dynamic properties that can't be added with 10 jsc_class_add_property() for example to implement something like imports object in seed/gjs. 11 12 * API/glib/JSCClass.cpp: 13 (VTableExceptionHandler::VTableExceptionHandler): Helper class to handle the exceptions in vtable functions that 14 can throw exceptions. 15 (VTableExceptionHandler::~VTableExceptionHandler): 16 (getProperty): Iterate the class chain to call get_property function. 17 (setProperty): Iterate the class chain to call set_property function. 18 (hasProperty): Iterate the class chain to call has_property function. 19 (deleteProperty): Iterate the class chain to call delete_property function. 20 (getPropertyNames): Iterate the class chain to call enumerate_properties function. 21 (jsc_class_class_init): Remove constructed implementation, since we need to initialize the JSClassDefinition in 22 jscClassCreate now. 23 (jscClassCreate): Receive an optional JSCClassVTable that is used to initialize the JSClassDefinition. 24 * API/glib/JSCClass.h: 25 * API/glib/JSCClassPrivate.h: 26 * API/glib/JSCContext.cpp: 27 (jscContextGetRegisteredClass): Helper to get the JSCClass for a given JSClassRef. 28 (jsc_context_register_class): Add JSCClassVTable parameter. 29 * API/glib/JSCContext.h: 30 * API/glib/JSCContextPrivate.h: 31 * API/glib/JSCWrapperMap.cpp: 32 (JSC::WrapperMap::registeredClass const): Get the JSCClass for a given JSClassRef. 33 * API/glib/JSCWrapperMap.h: 34 * API/glib/docs/jsc-glib-4.0-sections.txt: Add new symbols. 35 1 36 2018-04-17 Mark Lam <mark.lam@apple.com> 2 37 -
trunk/Tools/ChangeLog
r230752 r230753 1 2018-04-17 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GLIB] Make it possible to handle JSCClass external properties not added to the prototype 4 https://bugs.webkit.org/show_bug.cgi?id=184687 5 6 Reviewed by Michael Catanzaro. 7 8 Add test cases for the new API. 9 10 * TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp: 11 (fooCreate): 12 (fooFree): 13 (fooGetProperty): 14 (fooSetProperty): 15 (testJSCPromises): 16 (testJSCGarbageCollector): 17 (testsJSCVirtualMachine): 18 * TestWebKitAPI/Tests/WebKitGLib/WebProcessTest.cpp: 19 (windowObjectClearedCallback): 20 1 21 2018-04-17 Wenson Hsieh <wenson_hsieh@apple.com> 2 22 -
trunk/Tools/TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp
r230705 r230753 945 945 struct _Foo { 946 946 int foo; 947 HashMap<CString, int> properties; 947 948 Foo* sibling; 948 949 }; … … 950 951 static Foo* fooCreate() 951 952 { 952 return g_new0(Foo, 1); 953 Foo* foo = g_new0(Foo, 1); 954 new (foo) Foo(); 955 return foo; 953 956 } 954 957 … … 962 965 static void fooFree(Foo* foo) 963 966 { 967 foo->~Foo(); 964 968 g_free(foo); 965 969 } … … 988 992 { 989 993 foo->foo *= multiplier; 994 } 995 996 static int fooGetProperty(Foo* foo, const char* name) 997 { 998 auto addResult = foo->properties.add(name, 0); 999 return addResult.iterator->value; 1000 } 1001 1002 static void fooSetProperty(Foo* foo, const char* name, int value) 1003 { 1004 auto addResult = foo->properties.add(name, value); 1005 if (!addResult.isNewEntry) 1006 addResult.iterator->value = value; 990 1007 } 991 1008 … … 1041 1058 } 1042 1059 1060 static JSCClassVTable fooVTable = { 1061 // get_property 1062 [](JSCClass* jscClass, JSCContext* context, gpointer instance, const char* name) -> JSCValue* { 1063 auto* checker = static_cast<LeakChecker*>(g_object_get_data(G_OBJECT(jscClass), "leak-checker")); 1064 checker->watch(context); 1065 1066 if (!g_str_has_prefix(name, "prop_")) 1067 return nullptr; 1068 1069 if (!g_strcmp0(name, "prop_throw_on_get")) { 1070 jsc_context_throw(context, "Invalid property"); 1071 return jsc_value_new_undefined(context); 1072 } 1073 1074 auto* foo = static_cast<Foo*>(instance); 1075 auto* returnValue = jsc_value_new_number(context, fooGetProperty(foo, name)); 1076 checker->watch(returnValue); 1077 return returnValue; 1078 }, 1079 // set_property 1080 [](JSCClass* jscClass, JSCContext* context, gpointer instance, const char* name, JSCValue* value) -> gboolean { 1081 auto* checker = static_cast<LeakChecker*>(g_object_get_data(G_OBJECT(jscClass), "leak-checker")); 1082 checker->watch(context); 1083 checker->watch(value); 1084 1085 if (!g_str_has_prefix(name, "prop_")) 1086 return FALSE; 1087 1088 if (!jsc_value_is_number(value)) { 1089 jsc_context_throw(context, "Invalid value set: only numbers are allowed"); 1090 return TRUE; 1091 } 1092 1093 auto* foo = static_cast<Foo*>(instance); 1094 fooSetProperty(foo, name, jsc_value_to_int32(value)); 1095 return true; 1096 }, 1097 // has_property 1098 [](JSCClass* jscClass, JSCContext* context, gpointer instance, const char* name) -> gboolean { 1099 auto* checker = static_cast<LeakChecker*>(g_object_get_data(G_OBJECT(jscClass), "leak-checker")); 1100 checker->watch(context); 1101 return g_str_has_prefix(name, "prop_"); 1102 }, 1103 // delete_property 1104 [](JSCClass* jscClass, JSCContext* context, gpointer instance, const char* name) -> gboolean { 1105 auto* checker = static_cast<LeakChecker*>(g_object_get_data(G_OBJECT(jscClass), "leak-checker")); 1106 checker->watch(context); 1107 1108 if (!g_strcmp0(name, "prop_cant_delete")) 1109 return FALSE; 1110 1111 if (!g_strcmp0(name, "prop_throw_on_delete")) { 1112 jsc_context_throw(context, "Invalid property"); 1113 return TRUE; 1114 } 1115 1116 auto* foo = static_cast<Foo*>(instance); 1117 if (!foo->properties.contains(name)) 1118 return FALSE; 1119 1120 foo->properties.remove(name); 1121 return TRUE; 1122 }, 1123 // enumerate_properties 1124 [](JSCClass* jscClass, JSCContext* context, gpointer instance) -> char** { 1125 auto* checker = static_cast<LeakChecker*>(g_object_get_data(G_OBJECT(jscClass), "leak-checker")); 1126 checker->watch(context); 1127 1128 auto* foo = static_cast<Foo*>(instance); 1129 GRefPtr<GPtrArray> properties = adoptGRef(g_ptr_array_new_with_free_func(g_free)); 1130 Vector<CString> names = copyToVector(foo->properties.keys()); 1131 std::sort(names.begin(), names.end()); 1132 for (const auto& name : names) { 1133 if (g_str_has_prefix(name.data(), "prop_enum_")) 1134 g_ptr_array_add(properties.get(), g_strdup(name.data())); 1135 } 1136 if (!properties->len) 1137 return nullptr; 1138 1139 g_ptr_array_add(properties.get(), nullptr); 1140 return reinterpret_cast<char**>(g_ptr_array_free(properties.leakRef(), FALSE)); 1141 }, 1142 // padding 1143 nullptr, nullptr, nullptr, nullptr 1144 }; 1145 1043 1146 static void testJSCClass() 1044 1147 { … … 1049 1152 ExceptionHandler exceptionHandler(context.get()); 1050 1153 1051 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1154 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1052 1155 checker.watch(jscClass); 1053 1156 g_assert_false(jsc_class_get_parent(jscClass)); … … 1140 1243 g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 52); 1141 1244 1142 JSCClass* otherClass = jsc_context_register_class(context.get(), "Baz", nullptr, g_free);1245 JSCClass* otherClass = jsc_context_register_class(context.get(), "Baz", nullptr, nullptr, g_free); 1143 1246 checker.watch(otherClass); 1144 1247 g_assert_false(jsc_class_get_parent(otherClass)); … … 1165 1268 ExceptionHandler exceptionHandler(context.get()); 1166 1269 1167 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1270 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1168 1271 checker.watch(jscClass); 1169 1272 … … 1206 1309 ExceptionHandler exceptionHandler(context.get()); 1207 1310 1208 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1311 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1209 1312 checker.watch(jscClass); 1210 1313 … … 1241 1344 g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 42); 1242 1345 1243 JSCClass* bazClass = jsc_context_register_class(context.get(), "Baz", nullptr, g_free);1346 JSCClass* bazClass = jsc_context_register_class(context.get(), "Baz", nullptr, nullptr, g_free); 1244 1347 checker.watch(bazClass); 1245 1348 … … 1286 1389 ExceptionHandler exceptionHandler(context.get()); 1287 1390 1288 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1391 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1289 1392 checker.watch(jscClass); 1290 1393 … … 1328 1431 ExceptionHandler exceptionHandler(context.get()); 1329 1432 1330 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1433 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1331 1434 checker.watch(jscClass); 1332 1435 g_assert_false(jsc_class_get_parent(jscClass)); … … 1367 1470 ExceptionHandler exceptionHandler(context.get()); 1368 1471 1369 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1472 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1370 1473 checker.watch(jscClass); 1371 1474 g_assert_false(jsc_class_get_parent(jscClass)); … … 1395 1498 jsc_context_set_value(context.get(), "wk", jsNamespace.get()); 1396 1499 1397 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1500 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1398 1501 checker.watch(jscClass); 1399 1502 … … 1472 1575 g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 62); 1473 1576 } 1577 1578 { 1579 LeakChecker checker; 1580 GRefPtr<JSCContext> context = adoptGRef(jsc_context_new()); 1581 checker.watch(context.get()); 1582 ExceptionHandler exceptionHandler(context.get()); 1583 1584 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, &fooVTable, reinterpret_cast<GDestroyNotify>(fooFree)); 1585 checker.watch(jscClass); 1586 g_object_set_data(G_OBJECT(jscClass), "leak-checker", &checker); 1587 1588 GRefPtr<JSCValue> constructor = adoptGRef(jsc_class_add_constructor(jscClass, nullptr, G_CALLBACK(fooCreate), nullptr, nullptr, G_TYPE_POINTER, 0, G_TYPE_NONE)); 1589 checker.watch(constructor.get()); 1590 g_assert_true(jsc_value_is_constructor(constructor.get())); 1591 jsc_context_set_value(context.get(), jsc_class_get_name(jscClass), constructor.get()); 1592 jsc_class_add_property(jscClass, "foo", G_TYPE_INT, G_CALLBACK(getFoo), G_CALLBACK(setFoo), nullptr, nullptr); 1593 1594 GRefPtr<JSCValue> foo = adoptGRef(jsc_context_evaluate(context.get(), "f = new Foo();", -1)); 1595 checker.watch(foo.get()); 1596 g_assert_true(jsc_value_is_object(foo.get())); 1597 g_assert_true(jsc_value_object_has_property(foo.get(), "foo")); 1598 1599 g_assert_true(jsc_value_object_has_property(foo.get(), "prop_whatever")); 1600 g_assert_false(jsc_value_object_has_property(foo.get(), "whatever_prop")); 1601 1602 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(foo.get())); 1603 g_assert_null(properties.get()); 1604 1605 GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_1", -1)); 1606 checker.watch(result.get()); 1607 g_assert_true(jsc_value_is_number(result.get())); 1608 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 0); 1609 1610 GRefPtr<JSCValue> value = adoptGRef(jsc_value_object_get_property(foo.get(), "prop_1")); 1611 checker.watch(value.get()); 1612 g_assert_true(value.get() == result.get()); 1613 1614 result = adoptGRef(jsc_context_evaluate(context.get(), "f.foo", -1)); 1615 checker.watch(result.get()); 1616 g_assert_true(jsc_value_is_number(result.get())); 1617 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 0); 1618 1619 value = adoptGRef(jsc_value_object_get_property(foo.get(), "foo")); 1620 checker.watch(value.get()); 1621 g_assert_true(value.get() == result.get()); 1622 1623 result = adoptGRef(jsc_context_evaluate(context.get(), "'foo' in f.__proto__", -1)); 1624 checker.watch(result.get()); 1625 g_assert_true(jsc_value_is_boolean(result.get())); 1626 g_assert_true(jsc_value_to_boolean(result.get())); 1627 1628 result = adoptGRef(jsc_context_evaluate(context.get(), "'foo' in f", -1)); 1629 checker.watch(result.get()); 1630 g_assert_true(jsc_value_is_boolean(result.get())); 1631 g_assert_true(jsc_value_to_boolean(result.get())); 1632 1633 result = adoptGRef(jsc_context_evaluate(context.get(), "'prop_1' in f.__proto__", -1)); 1634 checker.watch(result.get()); 1635 g_assert_true(jsc_value_is_boolean(result.get())); 1636 g_assert_false(jsc_value_to_boolean(result.get())); 1637 1638 result = adoptGRef(jsc_context_evaluate(context.get(), "'prop_1' in f", -1)); 1639 checker.watch(result.get()); 1640 g_assert_true(jsc_value_is_boolean(result.get())); 1641 g_assert_true(jsc_value_to_boolean(result.get())); 1642 1643 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_1 = 25", -1)); 1644 checker.watch(result.get()); 1645 g_assert_true(jsc_value_is_number(result.get())); 1646 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 25); 1647 1648 g_assert_true(jsc_value_object_delete_property(foo.get(), "prop_1")); 1649 g_assert_true(jsc_value_object_has_property(foo.get(), "prop_1")); 1650 value = adoptGRef(jsc_value_object_get_property(foo.get(), "prop_1")); 1651 checker.watch(value.get()); 1652 g_assert_true(jsc_value_is_number(value.get())); 1653 g_assert_cmpuint(jsc_value_to_int32(value.get()), ==, 0); 1654 1655 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_cant_delete = 125", -1)); 1656 checker.watch(result.get()); 1657 g_assert_true(jsc_value_is_number(result.get())); 1658 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 125); 1659 jsc_value_object_delete_property(foo.get(), "prop_cant_delete"); 1660 g_assert_true(jsc_value_object_has_property(foo.get(), "prop_cant_delete")); 1661 value = adoptGRef(jsc_value_object_get_property(foo.get(), "prop_cant_delete")); 1662 checker.watch(value.get()); 1663 g_assert_true(jsc_value_is_number(value.get())); 1664 g_assert_cmpuint(jsc_value_to_int32(value.get()), ==, 125); 1665 1666 value = adoptGRef(jsc_value_new_number(context.get(), 42)); 1667 checker.watch(value.get()); 1668 jsc_value_object_set_property(foo.get(), "prop_1", value.get()); 1669 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_1", -1)); 1670 checker.watch(result.get()); 1671 g_assert_true(value.get() == result.get()); 1672 1673 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_2 = 35", -1)); 1674 checker.watch(result.get()); 1675 g_assert_true(jsc_value_is_number(result.get())); 1676 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 35); 1677 1678 result = adoptGRef(jsc_context_evaluate(context.get(), "'prop_2' in f.__proto__", -1)); 1679 checker.watch(result.get()); 1680 g_assert_true(jsc_value_is_boolean(result.get())); 1681 g_assert_false(jsc_value_to_boolean(result.get())); 1682 1683 result = adoptGRef(jsc_context_evaluate(context.get(), "'prop_2' in f", -1)); 1684 checker.watch(result.get()); 1685 g_assert_true(jsc_value_is_boolean(result.get())); 1686 g_assert_true(jsc_value_to_boolean(result.get())); 1687 1688 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_enum_1 = 250", -1)); 1689 checker.watch(result.get()); 1690 g_assert_true(jsc_value_is_number(result.get())); 1691 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 250); 1692 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_enum_2 = 450", -1)); 1693 checker.watch(result.get()); 1694 g_assert_true(jsc_value_is_number(result.get())); 1695 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 450); 1696 1697 properties.reset(jsc_value_object_enumerate_properties(foo.get())); 1698 g_assert_cmpuint(g_strv_length(properties.get()), ==, 2); 1699 g_assert_cmpstr(properties.get()[0], ==, "prop_enum_1"); 1700 g_assert_cmpstr(properties.get()[1], ==, "prop_enum_2"); 1701 g_assert_null(properties.get()[2]); 1702 1703 g_assert_null(jsc_context_get_exception(context.get())); 1704 bool didThrow = false; 1705 g_assert_throw_begin(exceptionHandler, didThrow); 1706 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_throw_on_get", -1)); 1707 checker.watch(result.get()); 1708 g_assert_true(jsc_value_is_undefined(result.get())); 1709 g_assert_did_throw(exceptionHandler, didThrow); 1710 g_assert_null(jsc_context_get_exception(context.get())); 1711 1712 didThrow = false; 1713 g_assert_throw_begin(exceptionHandler, didThrow); 1714 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_3 = 'not a number'", -1)); 1715 checker.watch(result.get()); 1716 g_assert_true(jsc_value_is_undefined(result.get())); 1717 g_assert_did_throw(exceptionHandler, didThrow); 1718 g_assert_null(jsc_context_get_exception(context.get())); 1719 1720 didThrow = false; 1721 g_assert_throw_begin(exceptionHandler, didThrow); 1722 jsc_value_object_delete_property(foo.get(), "prop_throw_on_delete"); 1723 g_assert_did_throw(exceptionHandler, didThrow); 1724 g_assert_null(jsc_context_get_exception(context.get())); 1725 1726 jsc_context_throw(context.get(), "Fake exception"); 1727 GRefPtr<JSCException> previousException = jsc_context_get_exception(context.get()); 1728 checker.watch(previousException.get()); 1729 didThrow = false; 1730 g_assert_throw_begin(exceptionHandler, didThrow); 1731 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_throw_on_get", -1)); 1732 checker.watch(result.get()); 1733 g_assert_true(jsc_value_is_undefined(result.get())); 1734 g_assert_did_throw(exceptionHandler, didThrow); 1735 g_assert_true(jsc_context_get_exception(context.get()) == previousException.get()); 1736 1737 didThrow = false; 1738 g_assert_throw_begin(exceptionHandler, didThrow); 1739 result = adoptGRef(jsc_context_evaluate(context.get(), "f.prop_3 = 'not a number'", -1)); 1740 checker.watch(result.get()); 1741 g_assert_true(jsc_value_is_undefined(result.get())); 1742 g_assert_did_throw(exceptionHandler, didThrow); 1743 g_assert_true(jsc_context_get_exception(context.get()) == previousException.get()); 1744 1745 didThrow = false; 1746 g_assert_throw_begin(exceptionHandler, didThrow); 1747 jsc_value_object_delete_property(foo.get(), "prop_throw_on_delete"); 1748 g_assert_did_throw(exceptionHandler, didThrow); 1749 g_assert_true(jsc_context_get_exception(context.get()) == previousException.get()); 1750 } 1474 1751 } 1475 1752 … … 1499 1776 } 1500 1777 1778 static JSCClassVTable barVTable = { 1779 // get_property 1780 nullptr, 1781 // set_property 1782 nullptr, 1783 // has_property 1784 nullptr, 1785 // delete_property 1786 nullptr, 1787 // enumerate_properties 1788 [](JSCClass* jscClass, JSCContext* context, gpointer instance) -> char** { 1789 auto* checker = static_cast<LeakChecker*>(g_object_get_data(G_OBJECT(jscClass), "leak-checker")); 1790 checker->watch(context); 1791 1792 auto* properties = static_cast<char**>(g_malloc0(2 * sizeof(char*))); 1793 properties[0] = g_strdup("bar"); 1794 return properties; 1795 }, 1796 // padding 1797 nullptr, nullptr, nullptr, nullptr 1798 }; 1799 1501 1800 static void testJSCPrototypes() 1502 1801 { … … 1507 1806 ExceptionHandler exceptionHandler(context.get()); 1508 1807 1509 JSCClass* fooClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));1808 JSCClass* fooClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1510 1809 checker.watch(fooClass); 1511 1810 g_assert_false(jsc_class_get_parent(fooClass)); … … 1517 1816 jsc_class_add_property(fooClass, "foo", G_TYPE_INT, G_CALLBACK(getFoo), G_CALLBACK(setFoo), nullptr, nullptr); 1518 1817 1519 JSCClass* barClass = jsc_context_register_class(context.get(), "Bar", fooClass, reinterpret_cast<GDestroyNotify>(barFree));1818 JSCClass* barClass = jsc_context_register_class(context.get(), "Bar", fooClass, nullptr, reinterpret_cast<GDestroyNotify>(barFree)); 1520 1819 checker.watch(barClass); 1521 1820 g_assert_true(jsc_class_get_parent(barClass) == fooClass); … … 1597 1896 g_assert_true(jsc_value_is_number(value.get())); 1598 1897 g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 84); 1898 } 1899 1900 { 1901 LeakChecker checker; 1902 GRefPtr<JSCContext> context = adoptGRef(jsc_context_new()); 1903 checker.watch(context.get()); 1904 ExceptionHandler exceptionHandler(context.get()); 1905 1906 JSCClass* fooClass = jsc_context_register_class(context.get(), "Foo", nullptr, &fooVTable, reinterpret_cast<GDestroyNotify>(fooFree)); 1907 checker.watch(fooClass); 1908 g_object_set_data(G_OBJECT(fooClass), "leak-checker", &checker); 1909 1910 GRefPtr<JSCValue> fooConstructor = adoptGRef(jsc_class_add_constructor(fooClass, nullptr, G_CALLBACK(fooCreate), nullptr, nullptr, G_TYPE_POINTER, 0, G_TYPE_NONE)); 1911 checker.watch(fooConstructor.get()); 1912 g_assert_true(jsc_value_is_constructor(fooConstructor.get())); 1913 jsc_context_set_value(context.get(), jsc_class_get_name(fooClass), fooConstructor.get()); 1914 jsc_class_add_property(fooClass, "foo", G_TYPE_INT, G_CALLBACK(getFoo), G_CALLBACK(setFoo), nullptr, nullptr); 1915 1916 JSCClass* barClass = jsc_context_register_class(context.get(), "Bar", fooClass, &barVTable, reinterpret_cast<GDestroyNotify>(barFree)); 1917 checker.watch(barClass); 1918 g_object_set_data(G_OBJECT(barClass), "leak-checker", &checker); 1919 g_assert_true(jsc_class_get_parent(barClass) == fooClass); 1920 GRefPtr<JSCValue> barConstructor = adoptGRef(jsc_class_add_constructor(barClass, nullptr, G_CALLBACK(barCreate), nullptr, nullptr, G_TYPE_POINTER, 0, G_TYPE_NONE)); 1921 checker.watch(barConstructor.get()); 1922 g_assert_true(jsc_value_is_constructor(barConstructor.get())); 1923 jsc_context_set_value(context.get(), jsc_class_get_name(barClass), barConstructor.get()); 1924 jsc_class_add_property(barClass, "bar", G_TYPE_INT, G_CALLBACK(getBar), G_CALLBACK(setBar), nullptr, nullptr); 1925 1926 GRefPtr<JSCValue> bar = adoptGRef(jsc_context_evaluate(context.get(), "b = new Bar();", -1)); 1927 checker.watch(bar.get()); 1928 g_assert_true(jsc_value_is_object(bar.get())); 1929 g_assert_true(jsc_value_object_has_property(bar.get(), "bar")); 1930 g_assert_true(jsc_value_object_has_property(bar.get(), "foo")); 1931 1932 g_assert_true(jsc_value_object_has_property(bar.get(), "prop_whatever")); 1933 g_assert_false(jsc_value_object_has_property(bar.get(), "whatever_prop")); 1934 1935 GUniquePtr<char*> properties(jsc_value_object_enumerate_properties(bar.get())); 1936 g_assert_cmpuint(g_strv_length(properties.get()), ==, 1); 1937 g_assert_cmpstr(properties.get()[0], ==, "bar"); 1938 g_assert_null(properties.get()[1]); 1939 1940 GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate(context.get(), "b.prop_1", -1)); 1941 checker.watch(result.get()); 1942 g_assert_true(jsc_value_is_number(result.get())); 1943 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 0); 1944 1945 GRefPtr<JSCValue> value = adoptGRef(jsc_value_object_get_property(bar.get(), "prop_1")); 1946 checker.watch(value.get()); 1947 g_assert_true(value.get() == result.get()); 1948 1949 g_assert_true(jsc_value_object_delete_property(bar.get(), "prop_1")); 1950 g_assert_true(jsc_value_object_has_property(bar.get(), "prop_1")); 1951 value = adoptGRef(jsc_value_object_get_property(bar.get(), "prop_1")); 1952 checker.watch(value.get()); 1953 g_assert_true(jsc_value_is_number(value.get())); 1954 g_assert_cmpuint(jsc_value_to_int32(value.get()), ==, 0); 1955 1956 result = adoptGRef(jsc_context_evaluate(context.get(), "b.prop_cant_delete = 125", -1)); 1957 checker.watch(result.get()); 1958 g_assert_true(jsc_value_is_number(result.get())); 1959 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 125); 1960 jsc_value_object_delete_property(bar.get(), "prop_cant_delete"); 1961 g_assert_true(jsc_value_object_has_property(bar.get(), "prop_cant_delete")); 1962 value = adoptGRef(jsc_value_object_get_property(bar.get(), "prop_cant_delete")); 1963 checker.watch(value.get()); 1964 g_assert_true(jsc_value_is_number(value.get())); 1965 g_assert_cmpuint(jsc_value_to_int32(value.get()), ==, 125); 1966 1967 result = adoptGRef(jsc_context_evaluate(context.get(), "b.prop_enum_1 = 250", -1)); 1968 checker.watch(result.get()); 1969 g_assert_true(jsc_value_is_number(result.get())); 1970 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 250); 1971 result = adoptGRef(jsc_context_evaluate(context.get(), "b.prop_enum_2 = 450", -1)); 1972 checker.watch(result.get()); 1973 g_assert_true(jsc_value_is_number(result.get())); 1974 g_assert_cmpuint(jsc_value_to_int32(result.get()), ==, 450); 1975 1976 properties.reset(jsc_value_object_enumerate_properties(bar.get())); 1977 g_assert_cmpuint(g_strv_length(properties.get()), ==, 3); 1978 g_assert_cmpstr(properties.get()[0], ==, "bar"); 1979 g_assert_cmpstr(properties.get()[1], ==, "prop_enum_1"); 1980 g_assert_cmpstr(properties.get()[2], ==, "prop_enum_2"); 1981 g_assert_null(properties.get()[3]); 1599 1982 } 1600 1983 } … … 1797 2180 ExceptionHandler exceptionHandler(context.get()); 1798 2181 1799 JSCClass* fooClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFree));2182 JSCClass* fooClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFree)); 1800 2183 checker.watch(fooClass); 1801 2184 g_assert_false(jsc_class_get_parent(fooClass)); … … 1891 2274 s_fooWasFreed = false; 1892 2275 1893 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFreeAndLog));2276 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFreeAndLog)); 1894 2277 checker.watch(jscClass); 1895 2278 g_assert_false(jsc_class_get_parent(jscClass)); … … 2109 2492 2110 2493 auto thread = Thread::create("JSCVirtualMachineTest", [&] { 2111 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, reinterpret_cast<GDestroyNotify>(fooFreeAndLog));2494 JSCClass* jscClass = jsc_context_register_class(context.get(), "Foo", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(fooFreeAndLog)); 2112 2495 checker.watch(jscClass); 2113 2496 g_assert_false(jsc_class_get_parent(jscClass)); -
trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/WebProcessTest.cpp
r229973 r230753 92 92 GRefPtr<JSCContext> context = adoptGRef(webkit_frame_get_js_context_for_script_world(frame, world)); 93 93 WebProcessTest::assertObjectIsDeletedWhenTestFinishes(G_OBJECT(context.get())); 94 auto* jsClass = jsc_context_register_class(context.get(), "WebProcessTestRunner", nullptr, reinterpret_cast<GDestroyNotify>(webProcessTestRunnerFinalize));94 auto* jsClass = jsc_context_register_class(context.get(), "WebProcessTestRunner", nullptr, nullptr, reinterpret_cast<GDestroyNotify>(webProcessTestRunnerFinalize)); 95 95 WebProcessTest::assertObjectIsDeletedWhenTestFinishes(G_OBJECT(jsClass)); 96 96 jsc_class_add_method(jsClass, "runTest", G_CALLBACK(runTest), NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
Note:
See TracChangeset
for help on using the changeset viewer.