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()