[gjs: 1/3] objectbox: Support native JSObject GType for signal parameters and properties
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/3] objectbox: Support native JSObject GType for signal parameters and properties
- Date: Sun, 7 Feb 2021 16:27:01 +0000 (UTC)
commit ac2e87c743207b8098b6a823f7bcf5dd18944ecf
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Wed Jun 5 22:08:10 2019 -0500
objectbox: Support native JSObject GType for signal parameters and properties
Define a new boxed 'JSObject' GType and use it to wrap native JSObjects.
To do this, create an ObjectBox class that automatically roots and unroots
a JSObject persistently.
This class uses a private constructor and a pimpl idiom to force the
allocation of the wrapper in the stack, that is doable using a 'boxed'
static method that returns a unique_ptr.
Internally the boxed wrapper uses a ref-counting system that allows us to
avoid copies and re-rooting.
Define GObject.TYPE_JSOBJECT as 'JSObject' GType and add an alias for the
JS Objects using the $gtype property.
Add a ParamSpec jsobject alias.
gi/value.cpp | 15 +-
gjs/context.cpp | 4 +
gjs/objectbox.cpp | 89 ++++++++++
gjs/objectbox.h | 31 ++++
installed-tests/js/testGObjectClass.js | 316 +++++++++++++++++++++++++++++++++
installed-tests/js/testParamSpec.js | 1 +
meson.build | 1 +
modules/core/overrides/GObject.js | 8 +
tools/run_iwyu.sh | 8 +-
9 files changed, 468 insertions(+), 5 deletions(-)
---
diff --git a/gi/value.cpp b/gi/value.cpp
index 7aabaa5a..c9bb7f25 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -40,6 +40,7 @@
#include "gjs/context-private.h"
#include "gjs/context.h"
#include "gjs/jsapi-util.h"
+#include "gjs/objectbox.h"
#include "util/log.h"
GJS_JSAPI_RETURN_CONVENTION
@@ -536,7 +537,10 @@ gjs_value_to_g_value_internal(JSContext *context,
if (value.isObject()) {
JS::RootedObject obj(context, &value.toObject());
- if (g_type_is_a(gtype, G_TYPE_ERROR)) {
+ if (g_type_is_a(gtype, ObjectBox::gtype())) {
+ g_value_set_boxed(gvalue, ObjectBox::boxed(context, obj).get());
+ return true;
+ } else if (g_type_is_a(gtype, G_TYPE_ERROR)) {
/* special case GError */
gboxed = ErrorBase::to_c_ptr(context, obj);
if (!gboxed)
@@ -852,6 +856,15 @@ gjs_value_from_g_value_internal(JSContext *context,
return true;
}
+ if (g_type_is_a(gtype, ObjectBox::gtype())) {
+ obj = ObjectBox::object_for_c_ptr(context,
+ static_cast<ObjectBox*>(gboxed));
+ if (!obj)
+ return false;
+ value_p.setObject(*obj);
+ return true;
+ }
+
/* special case GError */
if (g_type_is_a(gtype, G_TYPE_ERROR)) {
obj = ErrorInstance::object_for_c_ptr(context,
diff --git a/gjs/context.cpp b/gjs/context.cpp
index c3810d97..4d8e7144 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -72,6 +72,7 @@
#include "gjs/mem.h"
#include "gjs/module.h"
#include "gjs/native.h"
+#include "gjs/objectbox.h"
#include "gjs/profiler-private.h"
#include "gjs/profiler.h"
#include "modules/modules.h"
@@ -485,6 +486,9 @@ GjsContextPrivate::GjsContextPrivate(JSContext* cx, GjsContext* public_context)
m_atoms = new GjsAtoms();
+ if (ObjectBox::gtype() == 0)
+ g_error("Failed to initialize JSObject GType");
+
JS::RootedObject internal_global(
m_cx, gjs_create_global_object(cx, GjsGlobalType::INTERNAL));
diff --git a/gjs/objectbox.cpp b/gjs/objectbox.cpp
new file mode 100644
index 00000000..3bbef096
--- /dev/null
+++ b/gjs/objectbox.cpp
@@ -0,0 +1,89 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2019 Marco Trevisan <marco trevisan canonical com>
+
+#include <config.h>
+
+#include <stddef.h> // for size_t
+
+#include <glib.h>
+
+#include <js/ComparisonOperators.h>
+#include <js/RootingAPI.h>
+#include <js/TypeDecls.h>
+
+#include "gjs/jsapi-util.h"
+#include "gjs/objectbox.h"
+#include "util/log.h"
+
+/* gjs/objectbox.cpp - GObject boxed type used to "box" a JS object so that it
+ * can be passed to or returned from a GObject signal, or used as the type of a
+ * GObject property.
+ */
+
+struct ObjectBox::impl {
+ impl(ObjectBox* parent, JSContext* cx, JSObject* obj)
+ : m_parent(parent), m_root(cx, obj) {
+ g_atomic_ref_count_init(&m_refcount);
+ }
+
+ void ref() {
+ debug("incref");
+ g_atomic_ref_count_inc(&m_refcount);
+ }
+
+ void unref() {
+ debug("decref");
+ if (g_atomic_ref_count_dec(&m_refcount))
+ delete m_parent;
+ }
+
+ void debug(const char* what GJS_USED_VERBOSE_LIFECYCLE) {
+ gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
+ "%s: ObjectBox %p, JSObject %s", what, m_parent,
+ gjs_debug_object(m_root).c_str());
+ }
+
+ ObjectBox* m_parent;
+ JS::PersistentRooted<JSObject*> m_root;
+ gatomicrefcount m_refcount;
+};
+
+ObjectBox::ObjectBox(JSContext* cx, JSObject* obj)
+ : m_impl(std::make_unique<ObjectBox::impl>(this, cx, obj)) {}
+
+ObjectBox::Ptr ObjectBox::boxed(JSContext* cx, JSObject* obj) {
+ return ObjectBox::Ptr(new ObjectBox(cx, obj),
+ [](ObjectBox* box) { box->m_impl->unref(); });
+}
+
+JSObject* ObjectBox::object_for_c_ptr(JSContext* cx, ObjectBox* box) {
+ if (!box) {
+ gjs_throw(cx, "Cannot get JSObject for null ObjectBox pointer");
+ return nullptr;
+ }
+
+ box->m_impl->debug("retrieved JSObject");
+ return box->m_impl->m_root.get();
+}
+
+GType ObjectBox::gtype() {
+ static volatile size_t type_id = 0;
+
+ if (g_once_init_enter(&type_id)) {
+ auto objectbox_copy = [](void* boxed) -> void* {
+ auto* box = static_cast<ObjectBox*>(boxed);
+ box->m_impl->ref();
+ return box;
+ };
+ auto objectbox_free = [](void* boxed) {
+ auto* box = static_cast<ObjectBox*>(boxed);
+ box->m_impl->unref();
+ };
+ GType type = g_boxed_type_register_static("JSObject", objectbox_copy,
+ objectbox_free);
+ g_once_init_leave(&type_id, type);
+ }
+
+ return type_id;
+}
diff --git a/gjs/objectbox.h b/gjs/objectbox.h
new file mode 100644
index 00000000..62179fc2
--- /dev/null
+++ b/gjs/objectbox.h
@@ -0,0 +1,31 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2019 Marco Trevisan <marco trevisan canonical com>
+
+#pragma once
+
+#include <config.h>
+
+#include <memory>
+
+#include <glib-object.h>
+
+#include <js/TypeDecls.h>
+
+#include "gjs/macros.h"
+
+struct ObjectBox {
+ using Ptr = std::unique_ptr<ObjectBox, void (*)(ObjectBox*)>;
+
+ [[nodiscard]] static GType gtype();
+ [[nodiscard]] static ObjectBox::Ptr boxed(JSContext*, JSObject*);
+
+ GJS_JSAPI_RETURN_CONVENTION
+ static JSObject* object_for_c_ptr(JSContext*, ObjectBox*);
+
+ private:
+ ObjectBox(JSContext*, JSObject*);
+
+ struct impl;
+ std::unique_ptr<impl> m_impl;
+};
diff --git a/installed-tests/js/testGObjectClass.js b/installed-tests/js/testGObjectClass.js
index efd9bcfb..dd0f2dca 100644
--- a/installed-tests/js/testGObjectClass.js
+++ b/installed-tests/js/testGObjectClass.js
@@ -2,6 +2,8 @@
// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
// SPDX-FileCopyrightText: 2011 Giovanni Campagna <gcampagna src gnome org>
+const System = imports.system;
+
imports.gi.versions.Gtk = '3.0';
const Gio = imports.gi.Gio;
@@ -888,3 +890,317 @@ describe('Auto accessor generation', function () {
expect(() => (a.missingSetter = 1)).toThrowError(/setter/);
});
});
+
+const MyObjectWithJSObjectProperty = GObject.registerClass({
+ Properties: {
+ 'jsobj-prop': GObject.ParamSpec.jsobject('jsobj-prop', 'jsobj-prop', 'jsobj-prop',
+ GObject.ParamFlags.CONSTRUCT | GObject.ParamFlags.READWRITE, ''),
+ },
+}, class MyObjectWithJSObjectProperty extends GObject.Object {
+});
+
+describe('GObject class with JSObject property', function () {
+ it('assigns a valid JSObject on construct', function () {
+ let date = new Date();
+ let obj = new MyObjectWithJSObjectProperty({jsobj_prop: date});
+ expect(obj.jsobj_prop).toEqual(date);
+ expect(obj.jsobj_prop).not.toEqual(new Date(0));
+ expect(() => obj.jsobj_prop.setFullYear(1985)).not.toThrow();
+ expect(obj.jsobj_prop.getFullYear()).toEqual(1985);
+ });
+
+ it('Set null with an empty JSObject on construct', function () {
+ expect(new MyObjectWithJSObjectProperty().jsobj_prop).toBeNull();
+ expect(new MyObjectWithJSObjectProperty({}).jsobj_prop).toBeNull();
+ });
+
+ it('assigns a null JSObject on construct', function () {
+ expect(new MyObjectWithJSObjectProperty({jsobj_prop: null}).jsobj_prop)
+ .toBeNull();
+ });
+
+ it('assigns a JSObject Array on construct', function () {
+ expect(() => new MyObjectWithJSObjectProperty({jsobj_prop: [1, 2, 3]}))
+ .not.toThrow();
+ });
+
+ it('assigns a Function on construct', function () {
+ expect(() => new MyObjectWithJSObjectProperty({jsobj_prop: () => {
+ return true;
+ }})).not.toThrow();
+ });
+
+ it('throws an error when using a boolean value on construct', function () {
+ expect(() => new MyObjectWithJSObjectProperty({jsobj_prop: true}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using an int value on construct', function () {
+ expect(() => new MyObjectWithJSObjectProperty({jsobj_prop: 1}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using a numeric value on construct', function () {
+ expect(() => new MyObjectWithJSObjectProperty({jsobj_prop: Math.PI}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using a string value on construct', function () {
+ expect(() => new MyObjectWithJSObjectProperty({jsobj_prop: 'string'}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using an undefined value on construct', function () {
+ expect(() => new MyObjectWithJSObjectProperty({jsobj_prop: undefined})).toThrow();
+ });
+
+ it('property value survives when GObject wrapper is collected', function () {
+ const MyConverter = GObject.registerClass({
+ Properties: {
+ testprop: GObject.ParamSpec.jsobject('testprop', 'testprop', 'Test property',
+ GObject.ParamFlags.CONSTRUCT | GObject.ParamFlags.READWRITE),
+ },
+ Implements: [Gio.Converter],
+ }, class MyConverter extends GObject.Object {});
+
+ function stashObject() {
+ const base = new Gio.MemoryInputStream();
+ const converter = new MyConverter({testprop: [1, 2, 3]});
+ return Gio.ConverterInputStream.new(base, converter);
+ }
+
+ const stream = stashObject();
+ System.gc();
+ expect(stream.get_converter().testprop).toEqual([1, 2, 3]);
+ });
+});
+
+const MyObjectWithJSObjectSignals = GObject.registerClass({
+ Signals: {
+ 'send-object': {param_types: [GObject.TYPE_JSOBJECT]},
+ 'send-many-objects': {
+ param_types: [GObject.TYPE_JSOBJECT,
+ GObject.TYPE_JSOBJECT,
+ GObject.TYPE_JSOBJECT],
+ },
+ 'get-object': {
+ flags: GObject.SignalFlags.RUN_LAST,
+ accumulator: GObject.AccumulatorType.FIRST_WINS,
+ return_type: GObject.TYPE_JSOBJECT,
+ param_types: [GObject.TYPE_JSOBJECT],
+ },
+ },
+}, class MyObjectWithJSObjectSignals extends GObject.Object {
+ emitObject(obj) {
+ this.emit('send-object', obj);
+ }
+});
+
+describe('GObject class with JSObject signals', function () {
+ let myInstance;
+ beforeEach(function () {
+ myInstance = new MyObjectWithJSObjectSignals();
+ });
+
+ it('emits signal with null JSObject parameter', function () {
+ let customSpy = jasmine.createSpy('sendObjectSpy');
+ myInstance.connect('send-object', customSpy);
+ myInstance.emitObject(null);
+ expect(customSpy).toHaveBeenCalledWith(myInstance, null);
+ });
+
+ it('emits signal with JSObject parameter', function () {
+ let customSpy = jasmine.createSpy('sendObjectSpy');
+ myInstance.connect('send-object', customSpy);
+
+ let obj = {
+ foo: [1, 2, 3],
+ sub: {a: {}, 'b': this},
+ desc: 'test',
+ date: new Date(),
+ };
+ myInstance.emitObject(obj);
+ expect(customSpy).toHaveBeenCalledWith(myInstance, obj);
+ });
+
+ it('emits signal with multiple JSObject parameters', function () {
+ let customSpy = jasmine.createSpy('sendManyObjectsSpy');
+ myInstance.connect('send-many-objects', customSpy);
+
+ let obj = {
+ foo: [9, 8, 7, 'a', 'b', 'c'],
+ sub: {a: {}, 'b': this},
+ desc: 'test',
+ date: new RegExp('\\w+'),
+ };
+ myInstance.emit('send-many-objects', obj, obj.foo, obj.sub);
+ expect(customSpy).toHaveBeenCalledWith(myInstance, obj, obj.foo, obj.sub);
+ });
+
+ it('re-emits signal with same JSObject parameter', function () {
+ let obj = {
+ foo: [9, 8, 7, 'a', 'b', 'c'],
+ sub: {a: {}, 'b': this},
+ func: arg => {
+ return {ret: [arg]};
+ },
+ };
+
+ myInstance.connect('send-many-objects', (instance, func, args, foo) => {
+ expect(instance).toEqual(myInstance);
+ expect(System.addressOf(instance)).toEqual(System.addressOf(myInstance));
+ expect(foo).toEqual(obj.foo);
+ expect(System.addressOf(foo)).toEqual(System.addressOf(obj.foo));
+ expect(func(args).ret[0]).toEqual(args);
+ });
+ myInstance.connect('send-object', (instance, param) => {
+ expect(instance).toEqual(myInstance);
+ expect(System.addressOf(instance)).toEqual(System.addressOf(myInstance));
+ expect(param).toEqual(obj);
+ expect(System.addressOf(param)).toEqual(System.addressOf(obj));
+ expect(() => instance.emit('send-many-objects', param.func, param, param.foo))
+ .not.toThrow();
+ });
+
+ myInstance.emit('send-object', obj);
+ });
+
+ it('throws an error when using a boolean value as parameter', function () {
+ expect(() => myInstance.emit('send-object', true))
+ .toThrowError(/JSObject expected/);
+ expect(() => myInstance.emit('send-many-objects', ['a'], true, {}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using an int value as parameter', function () {
+ expect(() => myInstance.emit('send-object', 1))
+ .toThrowError(/JSObject expected/);
+ expect(() => myInstance.emit('send-many-objects', ['a'], 1, {}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using a numeric value as parameter', function () {
+ expect(() => myInstance.emit('send-object', Math.PI))
+ .toThrowError(/JSObject expected/);
+ expect(() => myInstance.emit('send-many-objects', ['a'], Math.PI, {}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using a string value as parameter', function () {
+ expect(() => myInstance.emit('send-object', 'string'))
+ .toThrowError(/JSObject expected/);
+ expect(() => myInstance.emit('send-many-objects', ['a'], 'string', {}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('throws an error when using an undefined value as parameter', function () {
+ expect(() => myInstance.emit('send-object', undefined))
+ .toThrowError(/JSObject expected/);
+ expect(() => myInstance.emit('send-many-objects', ['a'], undefined, {}))
+ .toThrowError(/JSObject expected/);
+ });
+
+ it('returns a JSObject', function () {
+ let data = {
+ foo: [9, 8, 7, 'a', 'b', 'c'],
+ sub: {a: {}, 'b': this},
+ func: arg => {
+ return {ret: [arg]};
+ },
+ };
+ let id = myInstance.connect('get-object', () => {
+ return data;
+ });
+ expect(myInstance.emit('get-object', {})).toBe(data);
+ myInstance.disconnect(id);
+
+ myInstance.connect('get-object', (instance, input) => {
+ if (input) {
+ if (typeof input === 'function')
+ input();
+ return input;
+ }
+
+ class SubObject {
+ constructor() {
+ this.pi = Math.PI;
+ }
+
+ method() {}
+
+ gobject() {
+ return GObject.Object;
+ }
+
+ get data() {
+ return data;
+ }
+ }
+
+ return new SubObject();
+ });
+
+ expect(myInstance.emit('get-object', null).constructor.name).toBe('SubObject');
+ expect(myInstance.emit('get-object', null).data).toBe(data);
+ expect(myInstance.emit('get-object', null).pi).toBe(Math.PI);
+ expect(() => myInstance.emit('get-object', null).method()).not.toThrow();
+ expect(myInstance.emit('get-object', null).gobject()).toBe(GObject.Object);
+ expect(new (myInstance.emit('get-object', null).gobject())() instanceof GObject.Object)
+ .toBeTruthy();
+ expect(myInstance.emit('get-object', data)).toBe(data);
+ expect(myInstance.emit('get-object', jasmine.createSpy('callMeSpy')))
+ .toHaveBeenCalled();
+ });
+
+ it('returns null when returning undefined', function () {
+ myInstance.connect('get-object', () => {
+ return undefined;
+ });
+ expect(myInstance.emit('get-object', {})).toBeNull();
+ });
+
+ it('returns null when not returning', function () {
+ myInstance.connect('get-object', () => { });
+ expect(myInstance.emit('get-object', {})).toBeNull();
+ });
+
+ // These tests are intended to throw an error, but currently errors cannot
+ // be caught from signal handlers, so we check for logged messages instead
+
+ it('throws an error when returning a boolean value', function () {
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+ '*JSObject expected*');
+ myInstance.connect('get-object', () => true);
+ myInstance.emit('get-object', {});
+ GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectClass.js', 0,
+ 'throws an error when returning a boolean value');
+ });
+
+ it('throws an error when returning an int value', function () {
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+ '*JSObject expected*');
+ myInstance.connect('get-object', () => 1);
+ myInstance.emit('get-object', {});
+ GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectClass.js', 0,
+ 'throws an error when returning a boolean value');
+ });
+
+ it('throws an error when returning a numeric value', function () {
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+ '*JSObject expected*');
+ myInstance.connect('get-object', () => Math.PI);
+ myInstance.emit('get-object', {});
+ GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectClass.js', 0,
+ 'throws an error when returning a boolean value');
+ });
+
+ it('throws an error when returning a string value', function () {
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+ '*JSObject expected*');
+ myInstance.connect('get-object', () => 'string');
+ myInstance.emit('get-object', {});
+ GLib.test_assert_expected_messages_internal('Gjs', 'testGObjectClass.js', 0,
+ 'throws an error when returning a boolean value');
+ });
+});
+
diff --git a/installed-tests/js/testParamSpec.js b/installed-tests/js/testParamSpec.js
index a3c45518..be64a34a 100644
--- a/installed-tests/js/testParamSpec.js
+++ b/installed-tests/js/testParamSpec.js
@@ -42,6 +42,7 @@ testParamSpec('enum', [Regress.TestEnum, Regress.TestEnum.VALUE2],
testParamSpec('flags', [Regress.TestFlags, Regress.TestFlags.FLAG2],
Regress.TestFlags.FLAG2);
testParamSpec('object', [GObject.Object], null);
+testParamSpec('jsobject', [], null);
describe('GObject.ParamSpec object', function () {
it("doesn't crash when resolving a non-string property", function () {
diff --git a/meson.build b/meson.build
index 27a6cb9b..23e6ae76 100644
--- a/meson.build
+++ b/meson.build
@@ -406,6 +406,7 @@ libgjs_sources = [
'gjs/mem.cpp', 'gjs/mem-private.h',
'gjs/module.cpp', 'gjs/module.h',
'gjs/native.cpp', 'gjs/native.h',
+ 'gjs/objectbox.cpp', 'gjs/objectbox.h',
'gjs/profiler.cpp', 'gjs/profiler-private.h',
'gjs/stack.cpp',
'modules/console.cpp', 'modules/console.h',
diff --git a/modules/core/overrides/GObject.js b/modules/core/overrides/GObject.js
index 5210a9e3..640a4fc6 100644
--- a/modules/core/overrides/GObject.js
+++ b/modules/core/overrides/GObject.js
@@ -261,6 +261,10 @@ function _init() {
GObject.String = String;
String.$gtype = GObject.TYPE_STRING;
+ GObject.TYPE_JSOBJECT = GObject.type_from_name('JSObject');
+ GObject.JSObject = Object;
+ Object.$gtype = GObject.TYPE_JSOBJECT;
+
GObject.TYPE_POINTER = GObject.type_from_name('gpointer');
GObject.TYPE_BOXED = GObject.type_from_name('GBoxed');
GObject.TYPE_PARAM = GObject.type_from_name('GParam');
@@ -334,6 +338,10 @@ function _init() {
return GObject.param_spec_object(name, nick, blurb, objectType, flags);
};
+ GObject.ParamSpec.jsobject = function (name, nick, blurb, flags) {
+ return GObject.param_spec_boxed(name, nick, blurb, Object.$gtype, flags);
+ };
+
GObject.ParamSpec.param = function (name, nick, blurb, flags, paramType) {
return GObject.param_spec_param(name, nick, blurb, paramType, flags);
};
diff --git a/tools/run_iwyu.sh b/tools/run_iwyu.sh
index 1efc5806..cae6fbeb 100755
--- a/tools/run_iwyu.sh
+++ b/tools/run_iwyu.sh
@@ -71,10 +71,10 @@ for FILE in $SRCDIR/gi/*.cpp $SRCDIR/gjs/atoms.cpp $SRCDIR/gjs/byteArray.cpp \
$SRCDIR/gjs/deprecation.cpp $SRCDIR/gjs/error-types.cpp \
$SRCDIR/gjs/engine.cpp $SRCDIR/gjs/global.cpp $SRCDIR/gjs/importer.cpp \
$SRCDIR/gjs/jsapi-util*.cpp $SRCDIR/gjs/module.cpp $SRCDIR/gjs/native.cpp \
- $SRCDIR/gjs/stack.cpp $SRCDIR/modules/cairo-*.cpp \
- $SRCDIR/modules/console.cpp $SRCDIR/modules/print.cpp \
- $SRCDIR/modules/system.cpp $SRCDIR/test/*.cpp $SRCDIR/util/*.cpp \
- $SRCDIR/libgjs-private/*.c
+ $SRCDIR/gjs/objectbox.cpp $SRCDIR/gjs/stack.cpp \
+ $SRCDIR/modules/cairo-*.cpp $SRCDIR/modules/console.cpp \
+ $SRCDIR/modules/print.cpp $SRCDIR/modules/system.cpp $SRCDIR/test/*.cpp \
+ $SRCDIR/util/*.cpp $SRCDIR/libgjs-private/*.c
do
if should_analyze $FILE; then
if ! $IWYU $FILE -- $PRIVATE_MAPPING | $POSTPROCESS; then
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]