Title: [234025] trunk
Revision
234025
Author
[email protected]
Date
2018-07-19 23:11:41 -0700 (Thu, 19 Jul 2018)

Log Message

[GLIB] jsc_context_evaluate_in_object() should receive an instance when a JSCClass is given
https://bugs.webkit.org/show_bug.cgi?id=187798

Reviewed by Michael Catanzaro.

Source/_javascript_Core:

Because a JSCClass is pretty much useless without an instance in this case. It should be similar to
jsc_value_new_object() because indeed we are creating a new object. This makes destroy function and vtable
functions to work. We can't use JSAPIWrapperObject to wrap this object, because it's a global object, so this
patch adds JSAPIWrapperGlobalObject or that.

* API/glib/JSAPIWrapperGlobalObject.cpp: Added.
(jsAPIWrapperGlobalObjectHandleOwner):
(JSAPIWrapperGlobalObjectHandleOwner::finalize):
(JSC::JSCallbackObject<JSAPIWrapperGlobalObject>::createStructure):
(JSC::JSCallbackObject<JSAPIWrapperGlobalObject>::create):
(JSC::JSAPIWrapperGlobalObject::JSAPIWrapperGlobalObject):
(JSC::JSAPIWrapperGlobalObject::finishCreation):
(JSC::JSAPIWrapperGlobalObject::visitChildren):
* API/glib/JSAPIWrapperGlobalObject.h: Added.
(JSC::JSAPIWrapperGlobalObject::wrappedObject const):
(JSC::JSAPIWrapperGlobalObject::setWrappedObject):
* API/glib/JSCClass.cpp:
(isWrappedObject): Helper to check if the given object is a JSAPIWrapperObject or JSAPIWrapperGlobalObject.
(wrappedObjectClass): Return the class of a wrapped object.
(jscContextForObject): Get the execution context of an object. If the object is a JSAPIWrapperGlobalObject, the
scope extension global object is used instead.
(getProperty): Use isWrappedObject, wrappedObjectClass and jscContextForObject.
(setProperty): Ditto.
(hasProperty): Ditto.
(deleteProperty): Ditto.
(getPropertyNames): Ditto.
(jscClassCreateContextWithJSWrapper): Call jscContextCreateContextWithJSWrapper().
* API/glib/JSCClassPrivate.h:
* API/glib/JSCContext.cpp:
(jscContextCreateContextWithJSWrapper): Call WrapperMap::createContextWithJSWrappper().
(jsc_context_evaluate_in_object): Use jscClassCreateContextWithJSWrapper() when a JSCClass is given.
* API/glib/JSCContext.h:
* API/glib/JSCContextPrivate.h:
* API/glib/JSCWrapperMap.cpp:
(JSC::WrapperMap::createContextWithJSWrappper): Create the new context for jsc_context_evaluate_in_object() here
when a JSCClass is used to create the JSAPIWrapperGlobalObject.
(JSC::WrapperMap::wrappedObject const): Return the wrapped object also in case of JSAPIWrapperGlobalObject.
* API/glib/JSCWrapperMap.h:
* GLib.cmake:

Tools:

Update test cases to the new API and use a destroy function and vtable in the test case of calling
jsc_context_evaluate_in_object() with a JSCClass.

* TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
(testJSCEvaluateInObject):

Modified Paths

Added Paths

Diff

Added: trunk/Source/_javascript_Core/API/glib/JSAPIWrapperGlobalObject.cpp (0 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSAPIWrapperGlobalObject.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/glib/JSAPIWrapperGlobalObject.cpp	2018-07-20 06:11:41 UTC (rev 234025)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSAPIWrapperGlobalObject.h"
+
+#include "JSCInlines.h"
+#include "JSCallbackObject.h"
+#include "Structure.h"
+#include <wtf/NeverDestroyed.h>
+
+class JSAPIWrapperGlobalObjectHandleOwner : public JSC::WeakHandleOwner {
+public:
+    void finalize(JSC::Handle<JSC::Unknown>, void*) override;
+};
+
+static JSAPIWrapperGlobalObjectHandleOwner* jsAPIWrapperGlobalObjectHandleOwner()
+{
+    static NeverDestroyed<JSAPIWrapperGlobalObjectHandleOwner> jsWrapperGlobalObjectHandleOwner;
+    return &jsWrapperGlobalObjectHandleOwner.get();
+}
+
+void JSAPIWrapperGlobalObjectHandleOwner::finalize(JSC::Handle<JSC::Unknown> handle, void*)
+{
+    auto* wrapperObject = static_cast<JSC::JSAPIWrapperGlobalObject*>(handle.get().asCell());
+    if (!wrapperObject->wrappedObject())
+        return;
+
+    JSC::Heap::heap(wrapperObject)->releaseSoon(std::unique_ptr<JSC::JSCGLibWrapperObject>(wrapperObject->wrappedObject()));
+    JSC::WeakSet::deallocate(JSC::WeakImpl::asWeakImpl(handle.slot()));
+}
+
+namespace JSC {
+
+template <> const ClassInfo JSCallbackObject<JSAPIWrapperGlobalObject>::s_info = { "JSAPIWrapperGlobalObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCallbackObject) };
+
+template<> const bool JSCallbackObject<JSAPIWrapperGlobalObject>::needsDestruction = false;
+
+template <>
+Structure* JSCallbackObject<JSAPIWrapperGlobalObject>::createStructure(VM& vm, JSGlobalObject*, JSValue proto)
+{
+    return Structure::create(vm, nullptr, proto, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
+}
+
+template<>
+JSCallbackObject<JSAPIWrapperGlobalObject>* JSCallbackObject<JSAPIWrapperGlobalObject>::create(VM& vm, JSClassRef classRef, Structure* structure)
+{
+    JSCallbackObject<JSAPIWrapperGlobalObject>* callbackObject = new (NotNull, allocateCell<JSCallbackObject<JSAPIWrapperGlobalObject>>(vm.heap)) JSCallbackObject(vm, classRef, structure);
+    callbackObject->finishCreation(vm);
+    return callbackObject;
+}
+
+JSAPIWrapperGlobalObject::JSAPIWrapperGlobalObject(VM& vm, Structure* structure)
+    : Base(vm, structure)
+{
+}
+
+void JSAPIWrapperGlobalObject::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    WeakSet::allocate(this, jsAPIWrapperGlobalObjectHandleOwner(), 0); // Balanced in JSAPIWrapperGlobalObjectHandleOwner::finalize.
+}
+
+void JSAPIWrapperGlobalObject::visitChildren(JSCell* cell, JSC::SlotVisitor& visitor)
+{
+    Base::visitChildren(cell, visitor);
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/API/glib/JSAPIWrapperGlobalObject.h (0 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSAPIWrapperGlobalObject.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/glib/JSAPIWrapperGlobalObject.h	2018-07-20 06:11:41 UTC (rev 234025)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSBase.h"
+#include "JSCGLibWrapperObject.h"
+#include "JSCPoison.h"
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+class JSAPIWrapperGlobalObject : public JSGlobalObject {
+public:
+    typedef JSGlobalObject Base;
+
+    void finishCreation(VM&);
+    static void visitChildren(JSCell*, JSC::SlotVisitor&);
+
+    JSCGLibWrapperObject* wrappedObject() const { return m_wrappedObject; }
+    void setWrappedObject(JSCGLibWrapperObject* wrappedObject) { m_wrappedObject = wrappedObject; }
+
+protected:
+    JSAPIWrapperGlobalObject(VM&, Structure*);
+
+private:
+    JSCGLibWrapperObject* m_wrappedObject;
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/API/glib/JSCClass.cpp (234024 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSCClass.cpp	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/API/glib/JSCClass.cpp	2018-07-20 06:11:41 UTC (rev 234025)
@@ -21,6 +21,7 @@
 #include "JSCClass.h"
 
 #include "APICast.h"
+#include "JSAPIWrapperGlobalObject.h"
 #include "JSAPIWrapperObject.h"
 #include "JSCCallbackFunction.h"
 #include "JSCClassPrivate.h"
@@ -108,15 +109,41 @@
     GRefPtr<JSCException> m_savedException;
 };
 
+static bool isWrappedObject(JSC::JSObject* jsObject)
+{
+    JSC::ExecState* exec = jsObject->globalObject()->globalExec();
+    if (jsObject->isGlobalObject())
+        return jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperGlobalObject>>(exec->vm());
+    return jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(exec->vm());
+}
+
+static JSClassRef wrappedObjectClass(JSC::JSObject* jsObject)
+{
+    ASSERT(isWrappedObject(jsObject));
+    if (jsObject->isGlobalObject())
+        return JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperGlobalObject>*>(jsObject)->classRef();
+    return JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef();
+}
+
+static GRefPtr<JSCContext> jscContextForObject(JSC::JSObject* jsObject)
+{
+    ASSERT(isWrappedObject(jsObject));
+    JSC::ExecState* exec = jsObject->globalObject()->globalExec();
+    if (jsObject->isGlobalObject()) {
+        if (auto* globalScopeExtension = exec->vmEntryGlobalObject()->globalScopeExtension())
+            exec = JSC::JSScope::objectAtScope(globalScopeExtension)->globalObject()->globalExec();
+    }
+    return jscContextGetOrCreate(toGlobalRef(exec));
+}
+
 static JSValueRef getProperty(JSContextRef callerContext, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
 {
     JSC::JSLockHolder locker(toJS(callerContext));
     auto* jsObject = toJS(object);
-    auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec()));
-    auto* jsContext = jscContextGetJSContext(context.get());
-    if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm()))
+    if (!isWrappedObject(jsObject))
         return nullptr;
 
+    auto context = jscContextForObject(jsObject);
     gpointer instance = jscContextWrappedObject(context.get(), object);
     if (!instance)
         return nullptr;
@@ -123,7 +150,7 @@
 
     VTableExceptionHandler exceptionHandler(context.get(), exception);
 
-    JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef();
+    JSClassRef jsClass = wrappedObjectClass(jsObject);
     for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) {
         if (!jscClass->priv->vtable)
             continue;
@@ -140,11 +167,10 @@
 {
     JSC::JSLockHolder locker(toJS(callerContext));
     auto* jsObject = toJS(object);
-    auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec()));
-    auto* jsContext = jscContextGetJSContext(context.get());
-    if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm()))
+    if (!isWrappedObject(jsObject))
         return false;
 
+    auto context = jscContextForObject(jsObject);
     gpointer instance = jscContextWrappedObject(context.get(), object);
     if (!instance)
         return false;
@@ -152,7 +178,7 @@
     VTableExceptionHandler exceptionHandler(context.get(), exception);
 
     GRefPtr<JSCValue> propertyValue;
-    JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef();
+    JSClassRef jsClass = wrappedObjectClass(jsObject);
     for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) {
         if (!jscClass->priv->vtable)
             continue;
@@ -171,16 +197,15 @@
 {
     JSC::JSLockHolder locker(toJS(callerContext));
     auto* jsObject = toJS(object);
-    auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec()));
-    auto* jsContext = jscContextGetJSContext(context.get());
-    if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm()))
+    if (!isWrappedObject(jsObject))
         return false;
 
+    auto context = jscContextForObject(jsObject);
     gpointer instance = jscContextWrappedObject(context.get(), object);
     if (!instance)
         return false;
 
-    JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef();
+    JSClassRef jsClass = wrappedObjectClass(jsObject);
     for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) {
         if (!jscClass->priv->vtable)
             continue;
@@ -198,11 +223,10 @@
 {
     JSC::JSLockHolder locker(toJS(callerContext));
     auto* jsObject = toJS(object);
-    auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec()));
-    auto* jsContext = jscContextGetJSContext(context.get());
-    if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm()))
+    if (!isWrappedObject(jsObject))
         return false;
 
+    auto context = jscContextForObject(jsObject);
     gpointer instance = jscContextWrappedObject(context.get(), object);
     if (!instance)
         return false;
@@ -209,7 +233,7 @@
 
     VTableExceptionHandler exceptionHandler(context.get(), exception);
 
-    JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef();
+    JSClassRef jsClass = wrappedObjectClass(jsObject);
     for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) {
         if (!jscClass->priv->vtable)
             continue;
@@ -226,16 +250,15 @@
 {
     JSC::JSLockHolder locker(toJS(callerContext));
     auto* jsObject = toJS(object);
-    auto context = jscContextGetOrCreate(toGlobalRef(jsObject->globalObject()->globalExec()));
-    auto* jsContext = jscContextGetJSContext(context.get());
-    if (!jsObject->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(toJS(jsContext)->vm()))
+    if (!isWrappedObject(jsObject))
         return;
 
+    auto context = jscContextForObject(jsObject);
     gpointer instance = jscContextWrappedObject(context.get(), object);
     if (!instance)
         return;
 
-    JSClassRef jsClass = JSC::jsCast<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>*>(jsObject)->classRef();
+    JSClassRef jsClass = wrappedObjectClass(jsObject);
     for (auto* jscClass = jscContextGetRegisteredClass(context.get(), jsClass); jscClass; jscClass = jscClass->priv->parentClass) {
         if (!jscClass->priv->vtable)
             continue;
@@ -486,6 +509,12 @@
     return jscContextGetOrCreateJSWrapper(priv->context, priv->jsClass, toRef(priv->prototype.get()), wrappedObject, priv->destroyFunction);
 }
 
+JSGlobalContextRef jscClassCreateContextWithJSWrapper(JSCClass* jscClass, gpointer wrappedObject)
+{
+    JSCClassPrivate* priv = jscClass->priv;
+    return jscContextCreateContextWithJSWrapper(priv->context, priv->jsClass, toRef(priv->prototype.get()), wrappedObject, priv->destroyFunction);
+}
+
 void jscClassInvalidate(JSCClass* jscClass)
 {
     jscClass->priv->context = nullptr;

Modified: trunk/Source/_javascript_Core/API/glib/JSCClassPrivate.h (234024 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSCClassPrivate.h	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/API/glib/JSCClassPrivate.h	2018-07-20 06:11:41 UTC (rev 234025)
@@ -28,4 +28,5 @@
 GRefPtr<JSCClass> jscClassCreate(JSCContext*, const char*, JSCClass*, JSCClassVTable*, GDestroyNotify);
 JSClassRef jscClassGetJSClass(JSCClass*);
 JSC::JSObject* jscClassGetOrCreateJSWrapper(JSCClass*, gpointer);
+JSGlobalContextRef jscClassCreateContextWithJSWrapper(JSCClass*, gpointer);
 void jscClassInvalidate(JSCClass*);

Modified: trunk/Source/_javascript_Core/API/glib/JSCContext.cpp (234024 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSCContext.cpp	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/API/glib/JSCContext.cpp	2018-07-20 06:11:41 UTC (rev 234025)
@@ -237,6 +237,11 @@
     return wrapperMap(context).createJSWrappper(context->priv->jsContext.get(), jsClass, prototype, wrappedObject, destroyFunction);
 }
 
+JSGlobalContextRef jscContextCreateContextWithJSWrapper(JSCContext* context, JSClassRef jsClass, JSValueRef prototype, gpointer wrappedObject, GDestroyNotify destroyFunction)
+{
+    return wrapperMap(context).createContextWithJSWrappper(jscVirtualMachineGetContextGroup(context->priv->vm.get()), jsClass, prototype, wrappedObject, destroyFunction);
+}
+
 gpointer jscContextWrappedObject(JSCContext* context, JSObjectRef jsObject)
 {
     return wrapperMap(context).wrappedObject(context->priv->jsContext.get(), jsObject);
@@ -795,6 +800,7 @@
  * @context: a #JSCContext
  * @code: a _javascript_ script to evaluate
  * @length: length of @code, or -1 if @code is a nul-terminated string
+ * @object_instance: (nullable): an object instance
  * @object_class: (nullable): a #JSCClass or %NULL to use the default
  * @uri: the source URI
  * @line_number: the starting line number
@@ -802,19 +808,21 @@
  *
  * Evaluate @code and create an new object where symbols defined in @code will be added as properties,
  * instead of being added to @context global object. The new object is returned as @object parameter.
+ * Similar to how jsc_value_new_object() works, if @object_instance is not %NULL @object_class must be provided too.
  * The @line_number is the starting line number in @uri; the value is one-based so the first line is 1.
  * @uri and @line_number will be shown in exceptions and they don't affect the behavior of the script.
  *
  * Returns: (transfer full): a #JSCValue representing the last value generated by the script.
  */
-JSCValue* jsc_context_evaluate_in_object(JSCContext* context, const char* code, gssize length, JSCClass* objectClass, const char* uri, unsigned lineNumber, JSCValue** object)
+JSCValue* jsc_context_evaluate_in_object(JSCContext* context, const char* code, gssize length, gpointer instance, JSCClass* objectClass, const char* uri, unsigned lineNumber, JSCValue** object)
 {
     g_return_val_if_fail(JSC_IS_CONTEXT(context), nullptr);
     g_return_val_if_fail(code, nullptr);
-    g_return_val_if_fail(!objectClass || JSC_IS_CLASS(objectClass), nullptr);
+    g_return_val_if_fail(!instance || JSC_IS_CLASS(objectClass), nullptr);
     g_return_val_if_fail(object && !*object, nullptr);
 
-    JSRetainPtr<JSGlobalContextRef> objectContext(Adopt, JSGlobalContextCreateInGroup(jscVirtualMachineGetContextGroup(context->priv->vm.get()), objectClass ? jscClassGetJSClass(objectClass) : nullptr));
+    JSRetainPtr<JSGlobalContextRef> objectContext(Adopt,
+        instance ? jscClassCreateContextWithJSWrapper(objectClass, instance) : JSGlobalContextCreateInGroup(jscVirtualMachineGetContextGroup(context->priv->vm.get()), nullptr));
     JSC::ExecState* exec = toJS(objectContext.get());
     auto* jsObject = exec->vmEntryGlobalObject();
     jsObject->setGlobalScopeExtension(JSC::JSWithScope::create(exec->vm(), jsObject, jsObject->globalScope(), toJS(JSContextGetGlobalObject(context->priv->jsContext.get()))));

Modified: trunk/Source/_javascript_Core/API/glib/JSCContext.h (234024 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSCContext.h	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/API/glib/JSCContext.h	2018-07-20 06:11:41 UTC (rev 234025)
@@ -132,6 +132,7 @@
 jsc_context_evaluate_in_object       (JSCContext         *context,
                                       const char         *code,
                                       gssize              length,
+                                      gpointer            object_instance,
                                       JSCClass           *object_class,
                                       const char         *uri,
                                       guint               line_number,

Modified: trunk/Source/_javascript_Core/API/glib/JSCContextPrivate.h (234024 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSCContextPrivate.h	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/API/glib/JSCContextPrivate.h	2018-07-20 06:11:41 UTC (rev 234025)
@@ -31,6 +31,7 @@
 void jscContextValueDestroyed(JSCContext*, JSValueRef);
 JSC::JSObject* jscContextGetJSWrapper(JSCContext*, gpointer);
 JSC::JSObject* jscContextGetOrCreateJSWrapper(JSCContext*, JSClassRef, JSValueRef prototype = nullptr, gpointer = nullptr, GDestroyNotify = nullptr);
+JSGlobalContextRef jscContextCreateContextWithJSWrapper(JSCContext*, JSClassRef, JSValueRef prototype = nullptr, gpointer = nullptr, GDestroyNotify = nullptr);
 gpointer jscContextWrappedObject(JSCContext*, JSObjectRef);
 JSCClass* jscContextGetRegisteredClass(JSCContext*, JSClassRef);
 

Modified: trunk/Source/_javascript_Core/API/glib/JSCWrapperMap.cpp (234024 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSCWrapperMap.cpp	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/API/glib/JSCWrapperMap.cpp	2018-07-20 06:11:41 UTC (rev 234025)
@@ -21,6 +21,7 @@
 #include "JSCWrapperMap.h"
 
 #include "APICast.h"
+#include "JSAPIWrapperGlobalObject.h"
 #include "JSAPIWrapperObject.h"
 #include "JSCClassPrivate.h"
 #include "JSCContextPrivate.h"
@@ -91,6 +92,26 @@
     return object;
 }
 
+JSGlobalContextRef WrapperMap::createContextWithJSWrappper(JSContextGroupRef jsGroup, JSClassRef jsClass, JSValueRef prototype, gpointer wrappedObject, GDestroyNotify destroyFunction)
+{
+    Ref<VM> vm(*toJS(jsGroup));
+    JSLockHolder locker(vm.ptr());
+    auto* globalObject = JSCallbackObject<JSAPIWrapperGlobalObject>::create(vm.get(), jsClass, JSCallbackObject<JSAPIWrapperGlobalObject>::createStructure(vm.get(), nullptr, jsNull()));
+    if (wrappedObject) {
+        globalObject->setWrappedObject(new JSC::JSCGLibWrapperObject(wrappedObject, destroyFunction));
+        m_cachedJSWrappers->set(wrappedObject, globalObject);
+    }
+    ExecState* exec = globalObject->globalExec();
+    if (prototype)
+        globalObject->resetPrototype(vm.get(), toJS(exec, prototype));
+    else if (auto jsPrototype = jsClass->prototype(exec))
+        globalObject->resetPrototype(vm.get(), jsPrototype);
+    else
+        globalObject->resetPrototype(vm.get(), jsNull());
+
+    return JSGlobalContextRetain(toGlobalRef(exec));
+}
+
 JSObject* WrapperMap::jsWrapper(gpointer wrappedObject) const
 {
     if (!wrappedObject)
@@ -108,6 +129,10 @@
         if (auto* wrapper = JSC::jsCast<JSC::JSAPIWrapperObject*>(object)->wrappedObject())
             return static_cast<JSC::JSCGLibWrapperObject*>(wrapper)->object();
     }
+    if (object->inherits(vm, JSC::JSCallbackObject<JSC::JSAPIWrapperGlobalObject>::info())) {
+        if (auto* wrapper = JSC::jsCast<JSC::JSAPIWrapperGlobalObject*>(object)->wrappedObject())
+            return wrapper->object();
+    }
     return nullptr;
 }
 

Modified: trunk/Source/_javascript_Core/API/glib/JSCWrapperMap.h (234024 => 234025)


--- trunk/Source/_javascript_Core/API/glib/JSCWrapperMap.h	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/API/glib/JSCWrapperMap.h	2018-07-20 06:11:41 UTC (rev 234025)
@@ -48,6 +48,7 @@
     JSCClass* registeredClass(JSClassRef) const;
 
     JSObject* createJSWrappper(JSGlobalContextRef, JSClassRef, JSValueRef prototype, gpointer, GDestroyNotify);
+    JSGlobalContextRef createContextWithJSWrappper(JSContextGroupRef, JSClassRef, JSValueRef prototype, gpointer, GDestroyNotify);
     JSObject* jsWrapper(gpointer wrappedObject) const;
     gpointer wrappedObject(JSGlobalContextRef, JSObjectRef) const;
 

Modified: trunk/Source/_javascript_Core/ChangeLog (234024 => 234025)


--- trunk/Source/_javascript_Core/ChangeLog	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-07-20 06:11:41 UTC (rev 234025)
@@ -1,3 +1,50 @@
+2018-07-19  Carlos Garcia Campos  <[email protected]>
+
+        [GLIB] jsc_context_evaluate_in_object() should receive an instance when a JSCClass is given
+        https://bugs.webkit.org/show_bug.cgi?id=187798
+
+        Reviewed by Michael Catanzaro.
+
+        Because a JSCClass is pretty much useless without an instance in this case. It should be similar to
+        jsc_value_new_object() because indeed we are creating a new object. This makes destroy function and vtable
+        functions to work. We can't use JSAPIWrapperObject to wrap this object, because it's a global object, so this
+        patch adds JSAPIWrapperGlobalObject or that.
+
+        * API/glib/JSAPIWrapperGlobalObject.cpp: Added.
+        (jsAPIWrapperGlobalObjectHandleOwner):
+        (JSAPIWrapperGlobalObjectHandleOwner::finalize):
+        (JSC::JSCallbackObject<JSAPIWrapperGlobalObject>::createStructure):
+        (JSC::JSCallbackObject<JSAPIWrapperGlobalObject>::create):
+        (JSC::JSAPIWrapperGlobalObject::JSAPIWrapperGlobalObject):
+        (JSC::JSAPIWrapperGlobalObject::finishCreation):
+        (JSC::JSAPIWrapperGlobalObject::visitChildren):
+        * API/glib/JSAPIWrapperGlobalObject.h: Added.
+        (JSC::JSAPIWrapperGlobalObject::wrappedObject const):
+        (JSC::JSAPIWrapperGlobalObject::setWrappedObject):
+        * API/glib/JSCClass.cpp:
+        (isWrappedObject): Helper to check if the given object is a JSAPIWrapperObject or JSAPIWrapperGlobalObject.
+        (wrappedObjectClass): Return the class of a wrapped object.
+        (jscContextForObject): Get the execution context of an object. If the object is a JSAPIWrapperGlobalObject, the
+        scope extension global object is used instead.
+        (getProperty): Use isWrappedObject, wrappedObjectClass and jscContextForObject.
+        (setProperty): Ditto.
+        (hasProperty): Ditto.
+        (deleteProperty): Ditto.
+        (getPropertyNames): Ditto.
+        (jscClassCreateContextWithJSWrapper): Call jscContextCreateContextWithJSWrapper().
+        * API/glib/JSCClassPrivate.h:
+        * API/glib/JSCContext.cpp:
+        (jscContextCreateContextWithJSWrapper): Call WrapperMap::createContextWithJSWrappper().
+        (jsc_context_evaluate_in_object): Use jscClassCreateContextWithJSWrapper() when a JSCClass is given.
+        * API/glib/JSCContext.h:
+        * API/glib/JSCContextPrivate.h:
+        * API/glib/JSCWrapperMap.cpp:
+        (JSC::WrapperMap::createContextWithJSWrappper): Create the new context for jsc_context_evaluate_in_object() here
+        when a JSCClass is used to create the JSAPIWrapperGlobalObject.
+        (JSC::WrapperMap::wrappedObject const): Return the wrapped object also in case of JSAPIWrapperGlobalObject.
+        * API/glib/JSCWrapperMap.h:
+        * GLib.cmake:
+
 2018-07-19  Saam Barati  <[email protected]>
 
         Conservatively make Object.assign's fast path do a two phase protocol of loading everything then storing everything to try to prevent a crash

Modified: trunk/Source/_javascript_Core/GLib.cmake (234024 => 234025)


--- trunk/Source/_javascript_Core/GLib.cmake	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Source/_javascript_Core/GLib.cmake	2018-07-20 06:11:41 UTC (rev 234025)
@@ -2,6 +2,7 @@
 file(MAKE_DIRECTORY ${DERIVED_SOURCES_JAVASCRIPCORE_GLIB_API_DIR})
 
 list(APPEND _javascript_Core_SOURCES
+    API/glib/JSAPIWrapperGlobalObject.cpp
     API/glib/JSAPIWrapperObjectGLib.cpp
     API/glib/JSCCallbackFunction.cpp
     API/glib/JSCClass.cpp

Modified: trunk/Tools/ChangeLog (234024 => 234025)


--- trunk/Tools/ChangeLog	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Tools/ChangeLog	2018-07-20 06:11:41 UTC (rev 234025)
@@ -1,3 +1,16 @@
+2018-07-19  Carlos Garcia Campos  <[email protected]>
+
+        [GLIB] jsc_context_evaluate_in_object() should receive an instance when a JSCClass is given
+        https://bugs.webkit.org/show_bug.cgi?id=187798
+
+        Reviewed by Michael Catanzaro.
+
+        Update test cases to the new API and use a destroy function and vtable in the test case of calling
+        jsc_context_evaluate_in_object() with a JSCClass.
+
+        * TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
+        (testJSCEvaluateInObject):
+
 2018-07-19  Ross Kirsling  <[email protected]>
 
         TestWTF.WTF.StringConcatenate_Unsigned fails for unsigned short on Windows

Modified: trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp (234024 => 234025)


--- trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2018-07-20 06:10:34 UTC (rev 234024)
+++ trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2018-07-20 06:11:41 UTC (rev 234025)
@@ -607,116 +607,160 @@
     g_assert_true(window2.get() == globalObject.get());
 }
 
+typedef struct {
+    const char* name;
+    bool wasDeleted;
+} Module;
+
+static JSCClassVTable moduleVTable = {
+    // get_property
+    [](JSCClass* jscClass, JSCContext* context, gpointer instance, const char* name) -> JSCValue* {
+        auto* checker = static_cast<LeakChecker*>(g_object_get_data(G_OBJECT(jscClass), "leak-checker"));
+        checker->watch(context);
+
+        if (g_strcmp0(name, "name"))
+            return nullptr;
+
+        auto* module = static_cast<Module*>(instance);
+        auto* returnValue = jsc_value_new_string(context, module->name);
+        checker->watch(returnValue);
+        return returnValue;
+    },
+    // set_property
+    nullptr,
+    // has_property
+    nullptr,
+    // delete_property
+    nullptr,
+    // enumerate_properties
+    nullptr,
+    // padding
+    nullptr, nullptr, nullptr, nullptr
+};
+
 static void testJSCEvaluateInObject()
 {
-    LeakChecker checker;
-    GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
-    checker.watch(context.get());
-    ExceptionHandler exceptionHandler(context.get());
+    Module moduleObject = { "ModuleWithClass", false };
+    {
+        LeakChecker checker;
+        GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+        checker.watch(context.get());
+        ExceptionHandler exceptionHandler(context.get());
 
-    GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate(context.get(), "g = 54; function foo() { return 42; }", -1));
-    checker.watch(result.get());
+        GRefPtr<JSCValue> result = adoptGRef(jsc_context_evaluate(context.get(), "g = 54; function foo() { return 42; }", -1));
+        checker.watch(result.get());
 
-    GRefPtr<JSCValue> globalObject = adoptGRef(jsc_context_get_global_object(context.get()));
-    checker.watch(globalObject.get());
+        GRefPtr<JSCValue> globalObject = adoptGRef(jsc_context_get_global_object(context.get()));
+        checker.watch(globalObject.get());
 
-    GRefPtr<JSCValue> rootFoo = adoptGRef(jsc_value_object_get_property(globalObject.get(), "foo"));
-    checker.watch(rootFoo.get());
-    g_assert(jsc_value_is_function(rootFoo.get()));
-    result = adoptGRef(jsc_value_function_call(rootFoo.get(), G_TYPE_NONE));
-    checker.watch(result.get());
-    g_assert_true(jsc_value_is_number(result.get()));
-    g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 42);
-    GRefPtr<JSCValue> value = adoptGRef(jsc_context_evaluate(context.get(), "foo()", -1));
-    checker.watch(value.get());
-    g_assert_true(value.get() == result.get());
+        GRefPtr<JSCValue> rootFoo = adoptGRef(jsc_value_object_get_property(globalObject.get(), "foo"));
+        checker.watch(rootFoo.get());
+        g_assert(jsc_value_is_function(rootFoo.get()));
+        result = adoptGRef(jsc_value_function_call(rootFoo.get(), G_TYPE_NONE));
+        checker.watch(result.get());
+        g_assert_true(jsc_value_is_number(result.get()));
+        g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 42);
+        GRefPtr<JSCValue> value = adoptGRef(jsc_context_evaluate(context.get(), "foo()", -1));
+        checker.watch(value.get());
+        g_assert_true(value.get() == result.get());
 
-    GRefPtr<JSCValue> module;
-    result = adoptGRef(jsc_context_evaluate_in_object(context.get(), "function bar() { return g; }", -1, nullptr, nullptr, 1, &module.outPtr()));
-    checker.watch(result.get());
-    checker.watch(module.get());
-    g_assert_true(JSC_IS_VALUE(module.get()));
-    g_assert_true(jsc_value_is_object(module.get()));
-    GUniquePtr<char> valueString(jsc_value_to_string(module.get()));
-    g_assert_cmpstr(valueString.get(), ==, "[object GlobalObject]");
-    jsc_context_set_value(context.get(), "module", module.get());
+        GRefPtr<JSCValue> module;
+        result = adoptGRef(jsc_context_evaluate_in_object(context.get(), "function bar() { return g; }", -1, nullptr, nullptr, nullptr, 1, &module.outPtr()));
+        checker.watch(result.get());
+        checker.watch(module.get());
+        g_assert_true(JSC_IS_VALUE(module.get()));
+        g_assert_true(jsc_value_is_object(module.get()));
+        GUniquePtr<char> valueString(jsc_value_to_string(module.get()));
+        g_assert_cmpstr(valueString.get(), ==, "[object GlobalObject]");
+        jsc_context_set_value(context.get(), "module", module.get());
 
-    GRefPtr<JSCValue> bar = adoptGRef(jsc_value_object_get_property(module.get(), "bar"));
-    checker.watch(bar.get());
-    g_assert_true(jsc_value_is_function(bar.get()));
-    result = adoptGRef(jsc_value_function_call(bar.get(), G_TYPE_NONE));
-    checker.watch(result.get());
-    g_assert_true(jsc_value_is_number(result.get()));
-    g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 54);
-    value = adoptGRef(jsc_context_evaluate(context.get(), "module.bar()", -1));
-    checker.watch(value.get());
-    g_assert_true(value.get() == result.get());
+        GRefPtr<JSCValue> bar = adoptGRef(jsc_value_object_get_property(module.get(), "bar"));
+        checker.watch(bar.get());
+        g_assert_true(jsc_value_is_function(bar.get()));
+        result = adoptGRef(jsc_value_function_call(bar.get(), G_TYPE_NONE));
+        checker.watch(result.get());
+        g_assert_true(jsc_value_is_number(result.get()));
+        g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 54);
+        value = adoptGRef(jsc_context_evaluate(context.get(), "module.bar()", -1));
+        checker.watch(value.get());
+        g_assert_true(value.get() == result.get());
 
-    bar = adoptGRef(jsc_context_get_value(context.get(), "bar"));
-    checker.watch(bar.get());
-    g_assert_true(jsc_value_is_undefined(bar.get()));
+        bar = adoptGRef(jsc_context_get_value(context.get(), "bar"));
+        checker.watch(bar.get());
+        g_assert_true(jsc_value_is_undefined(bar.get()));
 
-    JSCClass* jscClass = jsc_context_register_class(context.get(), "Module", nullptr, nullptr, nullptr);
-    checker.watch(jscClass);
-    GRefPtr<JSCValue> moduleWithClass;
-    result = adoptGRef(jsc_context_evaluate_in_object(context.get(), "function baz() { return foo(); }", -1, jscClass, nullptr, 1, &moduleWithClass.outPtr()));
-    checker.watch(result.get());
-    checker.watch(moduleWithClass.get());
-    g_assert_true(JSC_IS_VALUE(moduleWithClass.get()));
-    g_assert_true(jsc_value_is_object(moduleWithClass.get()));
-    valueString.reset(jsc_value_to_string(moduleWithClass.get()));
-    g_assert_cmpstr(valueString.get(), ==, "[object Module]");
-    jsc_context_set_value(context.get(), "moduleWithClass", moduleWithClass.get());
+        JSCClass* jscClass = jsc_context_register_class(context.get(), "Module", nullptr, &moduleVTable, [](gpointer module) {
+            static_cast<Module*>(module)->wasDeleted = true;
+        });
+        checker.watch(jscClass);
+        g_object_set_data(G_OBJECT(jscClass), "leak-checker", &checker);
+        GRefPtr<JSCValue> moduleWithClass;
+        result = adoptGRef(jsc_context_evaluate_in_object(context.get(), "function baz() { return foo(); }", -1, &moduleObject, jscClass, nullptr, 1, &moduleWithClass.outPtr()));
+        checker.watch(result.get());
+        checker.watch(moduleWithClass.get());
+        g_assert_true(JSC_IS_VALUE(moduleWithClass.get()));
+        g_assert_true(jsc_value_is_object(moduleWithClass.get()));
+        valueString.reset(jsc_value_to_string(moduleWithClass.get()));
+        g_assert_cmpstr(valueString.get(), ==, "[object Module]");
+        jsc_context_set_value(context.get(), "moduleWithClass", moduleWithClass.get());
 
-    GRefPtr<JSCValue> baz = adoptGRef(jsc_value_object_get_property(moduleWithClass.get(), "baz"));
-    checker.watch(baz.get());
-    g_assert_true(jsc_value_is_function(baz.get()));
-    result = adoptGRef(jsc_value_function_call(baz.get(), G_TYPE_NONE));
-    checker.watch(result.get());
-    g_assert_true(jsc_value_is_number(result.get()));
-    g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 42);
-    value = adoptGRef(jsc_context_evaluate(context.get(), "moduleWithClass.baz()", -1));
-    checker.watch(value.get());
-    g_assert_true(value.get() == result.get());
+        GRefPtr<JSCValue> name = adoptGRef(jsc_value_object_get_property(moduleWithClass.get(), "name"));
+        checker.watch(name.get());
+        g_assert_true(jsc_value_is_string(name.get()));
+        valueString.reset(jsc_value_to_string(name.get()));
+        g_assert_cmpstr(valueString.get(), ==, "ModuleWithClass");
 
-    bar = adoptGRef(jsc_value_object_get_property(moduleWithClass.get(), "bar"));
-    checker.watch(bar.get());
-    g_assert_true(jsc_value_is_undefined(bar.get()));
+        GRefPtr<JSCValue> baz = adoptGRef(jsc_value_object_get_property(moduleWithClass.get(), "baz"));
+        checker.watch(baz.get());
+        g_assert_true(jsc_value_is_function(baz.get()));
+        result = adoptGRef(jsc_value_function_call(baz.get(), G_TYPE_NONE));
+        checker.watch(result.get());
+        g_assert_true(jsc_value_is_number(result.get()));
+        g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 42);
+        value = adoptGRef(jsc_context_evaluate(context.get(), "moduleWithClass.baz()", -1));
+        checker.watch(value.get());
+        g_assert_true(value.get() == result.get());
 
-    baz = adoptGRef(jsc_value_object_get_property(module.get(), "baz"));
-    checker.watch(baz.get());
-    g_assert_true(jsc_value_is_undefined(baz.get()));
+        bar = adoptGRef(jsc_value_object_get_property(moduleWithClass.get(), "bar"));
+        checker.watch(bar.get());
+        g_assert_true(jsc_value_is_undefined(bar.get()));
 
-    baz = adoptGRef(jsc_context_get_value(context.get(), "baz"));
-    checker.watch(baz.get());
-    g_assert_true(jsc_value_is_undefined(baz.get()));
+        baz = adoptGRef(jsc_value_object_get_property(module.get(), "baz"));
+        checker.watch(baz.get());
+        g_assert_true(jsc_value_is_undefined(baz.get()));
 
-    GRefPtr<JSCValue> jsNamespace = adoptGRef(jsc_value_new_object(context.get(), nullptr, nullptr));
-    checker.watch(jsNamespace.get());
-    jsc_context_set_value(context.get(), "wk", jsNamespace.get());
+        baz = adoptGRef(jsc_context_get_value(context.get(), "baz"));
+        checker.watch(baz.get());
+        g_assert_true(jsc_value_is_undefined(baz.get()));
 
-    GRefPtr<JSCValue> moduleInWk;
-    result = adoptGRef(jsc_context_evaluate_in_object(context.get(), "function bar() { return g; }", -1, nullptr, nullptr, 1, &moduleInWk.outPtr()));
-    checker.watch(result.get());
-    checker.watch(moduleInWk.get());
-    g_assert_true(JSC_IS_VALUE(moduleInWk.get()));
-    g_assert_true(jsc_value_is_object(moduleInWk.get()));
-    jsc_value_object_set_property(jsNamespace.get(), "moduleInWk", moduleInWk.get());
+        GRefPtr<JSCValue> jsNamespace = adoptGRef(jsc_value_new_object(context.get(), nullptr, nullptr));
+        checker.watch(jsNamespace.get());
+        jsc_context_set_value(context.get(), "wk", jsNamespace.get());
 
-    bar = adoptGRef(jsc_value_object_get_property(moduleInWk.get(), "bar"));
-    checker.watch(bar.get());
-    g_assert_true(jsc_value_is_function(bar.get()));
-    result = adoptGRef(jsc_value_function_call(bar.get(), G_TYPE_NONE));
-    checker.watch(result.get());
-    g_assert_true(jsc_value_is_number(result.get()));
-    g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 54);
-    value = adoptGRef(jsc_context_evaluate(context.get(), "wk.moduleInWk.bar()", -1));
-    checker.watch(value.get());
-    g_assert_true(value.get() == result.get());
+        GRefPtr<JSCValue> moduleInWk;
+        result = adoptGRef(jsc_context_evaluate_in_object(context.get(), "function bar() { return g; }", -1, nullptr, nullptr, nullptr, 1, &moduleInWk.outPtr()));
+        checker.watch(result.get());
+        checker.watch(moduleInWk.get());
+        g_assert_true(JSC_IS_VALUE(moduleInWk.get()));
+        g_assert_true(jsc_value_is_object(moduleInWk.get()));
+        jsc_value_object_set_property(jsNamespace.get(), "moduleInWk", moduleInWk.get());
 
-    moduleInWk = adoptGRef(jsc_context_get_value(context.get(), "moduleInWk"));
-    checker.watch(moduleInWk.get());
-    g_assert_true(jsc_value_is_undefined(moduleInWk.get()));
+        bar = adoptGRef(jsc_value_object_get_property(moduleInWk.get(), "bar"));
+        checker.watch(bar.get());
+        g_assert_true(jsc_value_is_function(bar.get()));
+        result = adoptGRef(jsc_value_function_call(bar.get(), G_TYPE_NONE));
+        checker.watch(result.get());
+        g_assert_true(jsc_value_is_number(result.get()));
+        g_assert_cmpint(jsc_value_to_int32(result.get()), ==, 54);
+        value = adoptGRef(jsc_context_evaluate(context.get(), "wk.moduleInWk.bar()", -1));
+        checker.watch(value.get());
+        g_assert_true(value.get() == result.get());
+
+        moduleInWk = adoptGRef(jsc_context_get_value(context.get(), "moduleInWk"));
+        checker.watch(moduleInWk.get());
+        g_assert_true(jsc_value_is_undefined(moduleInWk.get()));
+    }
+    g_assert_true(moduleObject.wasDeleted);
 }
 
 static void testJSCCheckSyntax()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to