Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Commit bed6a5d

Browse files
[GTK][WPE] Initial implementation of JavaScriptCore glib bindings
https://bugs.webkit.org/show_bug.cgi?id=164061 Reviewed by Michael Catanzaro. .: Set global variables used by the makefiles. * Source/cmake/OptionsGTK.cmake: * Source/cmake/OptionsWPE.cmake: Source/JavaScriptCore: Add initial GLib API for JavaScriptCore. * API/JSAPIWrapperObject.h: * API/glib/JSAPIWrapperObjectGLib.cpp: Added. (jsAPIWrapperObjectHandleOwner): (JSAPIWrapperObjectHandleOwner::finalize): (JSAPIWrapperObjectHandleOwner::isReachableFromOpaqueRoots): (JSC::JSCallbackObject<JSAPIWrapperObject>::createStructure): (JSC::JSAPIWrapperObject::JSAPIWrapperObject): (JSC::JSAPIWrapperObject::finishCreation): (JSC::JSAPIWrapperObject::setWrappedObject): (JSC::JSAPIWrapperObject::visitChildren): * API/glib/JSCAutocleanups.h: Added. * API/glib/JSCCallbackFunction.cpp: Added. (JSC::callAsFunction): (JSC::callAsConstructor): (JSC::JSCCallbackFunction::create): (JSC::JSCCallbackFunction::JSCCallbackFunction): (JSC::JSCCallbackFunction::call): (JSC::JSCCallbackFunction::construct): (JSC::JSCCallbackFunction::destroy): * API/glib/JSCCallbackFunction.h: Added. (JSC::JSCCallbackFunction::createStructure): (JSC::JSCCallbackFunction::functionCallback): (JSC::JSCCallbackFunction::constructCallback): * API/glib/JSCClass.cpp: Added. (jscClassGetProperty): (jscClassSetProperty): (jscClassDispose): (jscClassConstructed): (jsc_class_class_init): (jscClassCreate): (jscClassGetJSClass): (jscClassGetOrCreateJSWrapper): (jscClassInvalidate): (jsc_class_get_name): (jsc_class_get_parent): (jsc_class_add_constructor): (jsc_class_add_method): (jsc_class_add_property): * API/glib/JSCClass.h: Added. * API/glib/JSCClassPrivate.h: Added. * API/glib/JSCContext.cpp: Added. (ExceptionHandler::ExceptionHandler): (ExceptionHandler::~ExceptionHandler): (jscContextSetVirtualMachine): (jscContextGetProperty): (jscContextSetProperty): (jscContextConstructed): (jscContextDispose): (jsc_context_class_init): (jscContextGetOrCreate): (jscContextGetJSContext): (wrapperMap): (jscContextGetOrCreateValue): (jscContextValueDestroyed): (jscContextGetJSWrapper): (jscContextGetOrCreateJSWrapper): (jscContextWrappedObject): (jscContextPushCallback): (jscContextPopCallback): (jscContextGArrayToJSArray): (jscContextJSArrayToGArray): (jscContextGValueToJSValue): (jscContextJSValueToGValue): (jsc_context_new): (jsc_context_new_with_virtual_machine): (jsc_context_get_virtual_machine): (jsc_context_get_exception): (jsc_context_throw): (jsc_context_throw_exception): (jsc_context_push_exception_handler): (jsc_context_pop_exception_handler): (jscContextHandleExceptionIfNeeded): (jsc_context_get_current): (jsc_context_evaluate): (jsc_context_evaluate_with_source_uri): (jsc_context_set_value): (jsc_context_get_value): (jsc_context_register_class): * API/glib/JSCContext.h: Added. * API/glib/JSCContextPrivate.h: Added. * API/glib/JSCDefines.h: Copied from Source/JavaScriptCore/API/JSAPIWrapperObject.h. * API/glib/JSCException.cpp: Added. (jscExceptionDispose): (jsc_exception_class_init): (jscExceptionCreate): (jscExceptionGetJSValue): (jscExceptionEnsureProperties): (jsc_exception_new): (jsc_exception_get_message): (jsc_exception_get_line_number): (jsc_exception_get_source_uri): * API/glib/JSCException.h: Added. * API/glib/JSCExceptionPrivate.h: Added. * API/glib/JSCGLibWrapperObject.h: Added. (JSC::JSCGLibWrapperObject::JSCGLibWrapperObject): (JSC::JSCGLibWrapperObject::~JSCGLibWrapperObject): (JSC::JSCGLibWrapperObject::object const): * API/glib/JSCValue.cpp: Added. (jscValueGetProperty): (jscValueSetProperty): (jscValueDispose): (jsc_value_class_init): (jscValueGetJSValue): (jscValueCreate): (jsc_value_get_context): (jsc_value_new_undefined): (jsc_value_is_undefined): (jsc_value_new_null): (jsc_value_is_null): (jsc_value_new_number): (jsc_value_is_number): (jsc_value_to_double): (jsc_value_to_int32): (jsc_value_new_boolean): (jsc_value_is_boolean): (jsc_value_to_boolean): (jsc_value_new_string): (jsc_value_is_string): (jsc_value_to_string): (jsc_value_new_array): (jsc_value_new_array_from_garray): (jsc_value_is_array): (jsc_value_new_object): (jsc_value_is_object): (jsc_value_object_is_instance_of): (jsc_value_object_set_property): (jsc_value_object_get_property): (jsc_value_object_set_property_at_index): (jsc_value_object_get_property_at_index): (jscValueCallFunction): (jsc_value_object_invoke_method): (jsc_value_object_define_property_data): (jsc_value_object_define_property_accessor): (jsc_value_new_function): (jsc_value_is_function): (jsc_value_function_call): (jsc_value_is_constructor): (jsc_value_constructor_call): * API/glib/JSCValue.h: Added. * API/glib/JSCValuePrivate.h: Added. * API/glib/JSCVersion.cpp: Added. (jsc_get_major_version): (jsc_get_minor_version): (jsc_get_micro_version): * API/glib/JSCVersion.h.in: Added. * API/glib/JSCVirtualMachine.cpp: Added. (addWrapper): (removeWrapper): (jscVirtualMachineSetContextGroup): (jscVirtualMachineEnsureContextGroup): (jscVirtualMachineDispose): (jsc_virtual_machine_class_init): (jscVirtualMachineGetOrCreate): (jscVirtualMachineGetContextGroup): (jscVirtualMachineAddContext): (jscVirtualMachineRemoveContext): (jscVirtualMachineGetContext): (jsc_virtual_machine_new): * API/glib/JSCVirtualMachine.h: Added. * API/glib/JSCVirtualMachinePrivate.h: Added. * API/glib/JSCWrapperMap.cpp: Added. (JSC::WrapperMap::WrapperMap): (JSC::WrapperMap::~WrapperMap): (JSC::WrapperMap::gobjectWrapper): (JSC::WrapperMap::unwrap): (JSC::WrapperMap::registerClass): (JSC::WrapperMap::createJSWrappper): (JSC::WrapperMap::jsWrapper const): (JSC::WrapperMap::wrappedObject const): * API/glib/JSCWrapperMap.h: Added. * API/glib/docs/jsc-glib-4.0-sections.txt: Added. * API/glib/docs/jsc-glib-4.0.types: Added. * API/glib/docs/jsc-glib-docs.sgml: Added. * API/glib/jsc.h: Added. * CMakeLists.txt: * GLib.cmake: Added. * JavaScriptCore.gir.in: Removed. * PlatformGTK.cmake: * PlatformWPE.cmake: * heap/Heap.cpp: (JSC::Heap::releaseDelayedReleasedObjects): * heap/Heap.h: * heap/HeapInlines.h: (JSC::Heap::releaseSoon): * javascriptcoregtk.pc.in: * runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::init): (JSC::JSGlobalObject::visitChildren): (JSC::JSGlobalObject::setWrapperMap): * runtime/JSGlobalObject.h: (JSC::JSGlobalObject::glibCallbackFunctionStructure const): (JSC::JSGlobalObject::glibWrapperObjectStructure const): (JSC::JSGlobalObject::wrapperMap const): Source/WebKit: Set decorator and deprecation_guard options in API docs config files, since they are no longer common to all libraries. * PlatformGTK.cmake: Tools: Add unit tests for the new API and generate the API documentation with generate-gtkdoc. * Scripts/webkitpy/style/checker.py: Ignore some style errors in public GLib API headers. * TestWebKitAPI/PlatformGTK.cmake: * TestWebKitAPI/PlatformWPE.cmake: * TestWebKitAPI/Tests/JavaScriptCore/glib/TestJSC.cpp: Added. (LeakChecker::~LeakChecker): (LeakChecker::watch): (ExceptionHandler::ExceptionHandler): (ExceptionHandler::~ExceptionHandler): (ExceptionHandler::push): (ExceptionHandler::pop): (jscContextGarbageCollect): (testJSCBasic): (testJSCTypes): (foo): (callback): (doubleAndSetInResult): (sumFunction): (testJSCFunction): (testJSCObject): (fooCreate): (fooCreateWithFoo): (fooFree): (setFoo): (getFoo): (setSibling): (getSibling): (multiplyFoo): (getMultiplyFoo): (getMultiplyFooAsync): (bazCreate): (testJSCClass): (barCreate): (barFree): (setBar): (getBar): (testJSCPrototypes): (createError): (testJSCExceptions): (testJSCPromises): (fooFreeAndLog): (testJSCGarbageCollector): (testsJSCVirtualMachine): (testsJSCAutocleanups): (main): * gtk/generate-gtkdoc: (get_generator_for_config): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@229798 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 671d954 commit bed6a5d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+6745
-34
lines changed

ChangeLog

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
2018-03-21 Carlos Garcia Campos <[email protected]>
2+
3+
[GTK][WPE] Initial implementation of JavaScriptCore glib bindings
4+
https://bugs.webkit.org/show_bug.cgi?id=164061
5+
6+
Reviewed by Michael Catanzaro.
7+
8+
Set global variables used by the makefiles.
9+
10+
* Source/cmake/OptionsGTK.cmake:
11+
* Source/cmake/OptionsWPE.cmake:
12+
113
2018-03-15 Ms2ger <[email protected]>
214

315
[GTK][WPE] Enable service workers

Source/JavaScriptCore/API/JSAPIWrapperObject.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#include "WeakReferenceHarvester.h"
3333
#include <wtf/Poisoned.h>
3434

35-
#if JSC_OBJC_API_ENABLED
35+
#if JSC_OBJC_API_ENABLED || defined(JSC_GLIB_API_ENABLED)
3636

3737
namespace JSC {
3838

@@ -55,6 +55,6 @@ class JSAPIWrapperObject : public JSDestructibleObject {
5555

5656
} // namespace JSC
5757

58-
#endif // JSC_OBJC_API_ENABLED
58+
#endif // JSC_OBJC_API_ENABLED || defined(JSC_GLIB_API_ENABLED)
5959

6060
#endif // JSAPIWrapperObject_h
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright (C) 2018 Igalia S.L.
3+
* Copyright (C) 2013-2018 Apple Inc. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* 1. Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* 2. Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
*
14+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24+
* THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#include "config.h"
28+
#include "JSAPIWrapperObject.h"
29+
30+
#include "JSCGLibWrapperObject.h"
31+
#include "JSCInlines.h"
32+
#include "JSCallbackObject.h"
33+
#include "Structure.h"
34+
#include <wtf/NeverDestroyed.h>
35+
36+
class JSAPIWrapperObjectHandleOwner : public JSC::WeakHandleOwner {
37+
public:
38+
void finalize(JSC::Handle<JSC::Unknown>, void*) override;
39+
bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override;
40+
};
41+
42+
static JSAPIWrapperObjectHandleOwner* jsAPIWrapperObjectHandleOwner()
43+
{
44+
static NeverDestroyed<JSAPIWrapperObjectHandleOwner> jsWrapperObjectHandleOwner;
45+
return &jsWrapperObjectHandleOwner.get();
46+
}
47+
48+
void JSAPIWrapperObjectHandleOwner::finalize(JSC::Handle<JSC::Unknown> handle, void*)
49+
{
50+
auto* wrapperObject = static_cast<JSC::JSAPIWrapperObject*>(handle.get().asCell());
51+
if (!wrapperObject->wrappedObject())
52+
return;
53+
54+
JSC::Heap::heap(wrapperObject)->releaseSoon(std::unique_ptr<JSC::JSCGLibWrapperObject>(static_cast<JSC::JSCGLibWrapperObject*>(wrapperObject->wrappedObject())));
55+
JSC::WeakSet::deallocate(JSC::WeakImpl::asWeakImpl(handle.slot()));
56+
}
57+
58+
bool JSAPIWrapperObjectHandleOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, JSC::SlotVisitor& visitor)
59+
{
60+
JSC::JSAPIWrapperObject* wrapperObject = JSC::jsCast<JSC::JSAPIWrapperObject*>(handle.get().asCell());
61+
// We use the JSGlobalObject when processing weak handles to prevent the situation where using
62+
// the same wrapped object in multiple global objects keeps all of the global objects alive.
63+
if (!wrapperObject->wrappedObject())
64+
return false;
65+
return JSC::Heap::isMarked(wrapperObject->structure()->globalObject()) && visitor.containsOpaqueRoot(wrapperObject->wrappedObject());
66+
}
67+
68+
namespace JSC {
69+
70+
template <> const ClassInfo JSCallbackObject<JSAPIWrapperObject>::s_info = { "JSAPIWrapperObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCallbackObject) };
71+
72+
template<> const bool JSCallbackObject<JSAPIWrapperObject>::needsDestruction = true;
73+
74+
template <>
75+
Structure* JSCallbackObject<JSAPIWrapperObject>::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
76+
{
77+
return Structure::create(vm, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
78+
}
79+
80+
JSAPIWrapperObject::JSAPIWrapperObject(VM& vm, Structure* structure)
81+
: Base(vm, structure)
82+
{
83+
}
84+
85+
void JSAPIWrapperObject::finishCreation(VM& vm)
86+
{
87+
Base::finishCreation(vm);
88+
WeakSet::allocate(this, jsAPIWrapperObjectHandleOwner(), 0); // Balanced in JSAPIWrapperObjectHandleOwner::finalize.
89+
}
90+
91+
void JSAPIWrapperObject::setWrappedObject(void* wrappedObject)
92+
{
93+
ASSERT(!m_wrappedObject);
94+
m_wrappedObject = wrappedObject;
95+
}
96+
97+
void JSAPIWrapperObject::visitChildren(JSCell* cell, JSC::SlotVisitor& visitor)
98+
{
99+
Base::visitChildren(cell, visitor);
100+
}
101+
102+
} // namespace JSC
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (C) 2018 Igalia S.L.
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Library General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Library General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Library General Public License
15+
* along with this library; see the file COPYING.LIB. If not, write to
16+
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17+
* Boston, MA 02110-1301, USA.
18+
*/
19+
20+
#if !defined(__JSC_H_INSIDE__) && !defined(JSC_COMPILATION)
21+
#error "Only <jsc/jsc.h> can be included directly."
22+
#endif
23+
24+
#ifndef JSCAutoPtr_h
25+
#define JSCAutoPtr_h
26+
27+
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
28+
#ifndef __GI_SCANNER__
29+
30+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (JSCClass, g_object_unref)
31+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (JSCContext, g_object_unref)
32+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (JSCException, g_object_unref)
33+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (JSCValue, g_object_unref)
34+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (JSCVirtualMachine, g_object_unref)
35+
36+
#endif /* __GI_SCANNER__ */
37+
#endif /* G_DEFINE_AUTOPTR_CLEANUP_FUNC */
38+
39+
#endif /* JSCAutoPtr_h */
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/*
2+
* Copyright (C) 2018 Igalia S.L.
3+
* Copyright (C) 2006, 2008, 2016 Apple Inc. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* 1. Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* 2. Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
*
14+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22+
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#include "config.h"
28+
#include "JSCCallbackFunction.h"
29+
30+
#include "APICallbackFunction.h"
31+
#include "APICast.h"
32+
#include "JSCClassPrivate.h"
33+
#include "JSCContextPrivate.h"
34+
#include "JSCExceptionPrivate.h"
35+
#include "JSCInlines.h"
36+
#include "JSFunction.h"
37+
#include "JSGlobalObject.h"
38+
#include "JSLock.h"
39+
40+
namespace JSC {
41+
42+
static JSValueRef callAsFunction(JSContextRef callerContext, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
43+
{
44+
return static_cast<JSCCallbackFunction*>(toJS(function))->call(callerContext, thisObject, argumentCount, arguments, exception);
45+
}
46+
47+
static JSObjectRef callAsConstructor(JSContextRef callerContext, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
48+
{
49+
return static_cast<JSCCallbackFunction*>(toJS(constructor))->construct(callerContext, argumentCount, arguments, exception);
50+
}
51+
52+
const ClassInfo JSCCallbackFunction::s_info = { "CallbackFunction", &InternalFunction::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCCallbackFunction) };
53+
54+
JSCCallbackFunction* JSCCallbackFunction::create(VM& vm, JSGlobalObject* globalObject, const String& name, Type type, JSCClass* jscClass, GRefPtr<GClosure>&& closure, GType returnType, Vector<GType>&& parameters)
55+
{
56+
Structure* structure = globalObject->glibCallbackFunctionStructure();
57+
JSCCallbackFunction* function = new (NotNull, allocateCell<JSCCallbackFunction>(vm.heap)) JSCCallbackFunction(vm, structure, type, jscClass, WTFMove(closure), returnType, WTFMove(parameters));
58+
function->finishCreation(vm, name);
59+
return function;
60+
}
61+
62+
JSCCallbackFunction::JSCCallbackFunction(VM& vm, Structure* structure, Type type, JSCClass* jscClass, GRefPtr<GClosure>&& closure, GType returnType, Vector<GType>&& parameters)
63+
: InternalFunction(vm, structure, APICallbackFunction::call<JSCCallbackFunction>, type == Type::Constructor ? APICallbackFunction::construct<JSCCallbackFunction> : nullptr)
64+
, m_functionCallback(callAsFunction)
65+
, m_constructCallback(callAsConstructor)
66+
, m_type(type)
67+
, m_class(jscClass)
68+
, m_closure(WTFMove(closure))
69+
, m_returnType(returnType)
70+
, m_parameters(WTFMove(parameters))
71+
{
72+
RELEASE_ASSERT(type != Type::Constructor || jscClass);
73+
if (G_CLOSURE_NEEDS_MARSHAL(m_closure.get()))
74+
g_closure_set_marshal(m_closure.get(), g_cclosure_marshal_generic);
75+
}
76+
77+
JSValueRef JSCCallbackFunction::call(JSContextRef callerContext, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
78+
{
79+
JSLockHolder locker(toJS(callerContext));
80+
auto context = jscContextGetOrCreate(toGlobalRef(globalObject()->globalExec()));
81+
auto* jsContext = jscContextGetJSContext(context.get());
82+
83+
if (m_type == Type::Constructor) {
84+
*exception = toRef(JSC::createTypeError(toJS(jsContext), ASCIILiteral("cannot call a class constructor without |new|")));
85+
return JSValueMakeUndefined(jsContext);
86+
}
87+
88+
gpointer instance = nullptr;
89+
if (m_type == Type::Method) {
90+
instance = jscContextWrappedObject(context.get(), thisObject);
91+
if (!instance) {
92+
*exception = toRef(JSC::createTypeError(toJS(jsContext), ASCIILiteral("invalid instance type in method")));
93+
return JSValueMakeUndefined(jsContext);
94+
}
95+
}
96+
97+
auto callbackData = jscContextPushCallback(context.get(), toRef(this), thisObject, argumentCount, arguments);
98+
99+
// GClosure always expect to have at least the instance parameter.
100+
bool addInstance = instance || m_parameters.isEmpty();
101+
102+
auto parameterCount = std::min(m_parameters.size(), argumentCount);
103+
if (addInstance)
104+
parameterCount++;
105+
auto* values = static_cast<GValue*>(g_alloca(sizeof(GValue) * parameterCount));
106+
memset(values, 0, sizeof(GValue) * parameterCount);
107+
108+
size_t firstParameter = 0;
109+
if (addInstance) {
110+
g_value_init(&values[0], G_TYPE_POINTER);
111+
g_value_set_pointer(&values[0], instance);
112+
firstParameter = 1;
113+
}
114+
for (size_t i = firstParameter; i < parameterCount && !*exception; ++i)
115+
jscContextJSValueToGValue(context.get(), arguments[i - firstParameter], m_parameters[i - firstParameter], &values[i], exception);
116+
117+
GValue returnValue = G_VALUE_INIT;
118+
if (m_returnType != G_TYPE_NONE)
119+
g_value_init(&returnValue, m_returnType);
120+
121+
if (!*exception)
122+
g_closure_invoke(m_closure.get(), m_returnType != G_TYPE_NONE ? &returnValue : nullptr, parameterCount, values, nullptr);
123+
124+
for (size_t i = 0; i < parameterCount; ++i)
125+
g_value_unset(&values[i]);
126+
127+
if (auto* jscException = jsc_context_get_exception(context.get()))
128+
*exception = jscExceptionGetJSValue(jscException);
129+
130+
jscContextPopCallback(context.get(), WTFMove(callbackData));
131+
132+
if (m_returnType == G_TYPE_NONE)
133+
return JSValueMakeUndefined(jsContext);
134+
135+
auto* retval = *exception ? JSValueMakeUndefined(jsContext) : jscContextGValueToJSValue(context.get(), &returnValue, exception);
136+
g_value_unset(&returnValue);
137+
return retval;
138+
}
139+
140+
JSObjectRef JSCCallbackFunction::construct(JSContextRef callerContext, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
141+
{
142+
JSLockHolder locker(toJS(callerContext));
143+
auto context = jscContextGetOrCreate(toGlobalRef(globalObject()->globalExec()));
144+
auto* jsContext = jscContextGetJSContext(context.get());
145+
146+
if (m_returnType == G_TYPE_NONE) {
147+
*exception = toRef(JSC::createTypeError(toJS(jsContext), ASCIILiteral("constructors cannot be void")));
148+
return nullptr;
149+
}
150+
151+
auto callbackData = jscContextPushCallback(context.get(), toRef(this), nullptr, argumentCount, arguments);
152+
153+
GValue returnValue = G_VALUE_INIT;
154+
g_value_init(&returnValue, m_returnType);
155+
156+
if (m_parameters.isEmpty()) {
157+
// GClosure always expect to have at least the instance parameter.
158+
GValue dummyValue = G_VALUE_INIT;
159+
g_value_init(&dummyValue, G_TYPE_POINTER);
160+
g_closure_invoke(m_closure.get(), &returnValue, 1, &dummyValue, nullptr);
161+
g_value_unset(&dummyValue);
162+
} else {
163+
auto parameterCount = std::min(m_parameters.size(), argumentCount);
164+
auto* values = static_cast<GValue*>(g_alloca(sizeof(GValue) * parameterCount));
165+
memset(values, 0, sizeof(GValue) * parameterCount);
166+
167+
for (size_t i = 0; i < parameterCount && !*exception; ++i)
168+
jscContextJSValueToGValue(context.get(), arguments[i], m_parameters[i], &values[i], exception);
169+
170+
if (!*exception)
171+
g_closure_invoke(m_closure.get(), &returnValue, parameterCount, values, nullptr);
172+
173+
for (size_t i = 0; i < parameterCount; ++i)
174+
g_value_unset(&values[i]);
175+
}
176+
177+
if (auto* jscException = jsc_context_get_exception(context.get()))
178+
*exception = jscExceptionGetJSValue(jscException);
179+
180+
jscContextPopCallback(context.get(), WTFMove(callbackData));
181+
182+
if (*exception) {
183+
g_value_unset(&returnValue);
184+
return nullptr;
185+
}
186+
187+
switch (g_type_fundamental(G_VALUE_TYPE(&returnValue))) {
188+
case G_TYPE_POINTER:
189+
case G_TYPE_OBJECT:
190+
if (auto* ptr = returnValue.data[0].v_pointer) {
191+
auto* retval = jscClassGetOrCreateJSWrapper(m_class.get(), ptr);
192+
g_value_unset(&returnValue);
193+
return toRef(retval);
194+
}
195+
*exception = toRef(JSC::createTypeError(toJS(jsContext), ASCIILiteral("constructor returned null")));
196+
break;
197+
default:
198+
*exception = toRef(JSC::createTypeError(toJS(jsContext), makeString("invalid type ", g_type_name(G_VALUE_TYPE(&returnValue)), " returned by constructor")));
199+
break;
200+
}
201+
return nullptr;
202+
}
203+
204+
void JSCCallbackFunction::destroy(JSCell* cell)
205+
{
206+
static_cast<JSCCallbackFunction*>(cell)->JSCCallbackFunction::~JSCCallbackFunction();
207+
}
208+
209+
} // namespace JSC

0 commit comments

Comments
 (0)