Skip to content
Commits on Source (20)
Version 1.68.3
--------------
- Crash and bug fixes backported from the development branch.
- Build fixes [Philip Chimento]
- Closed bugs and merge requests:
* win32: Fix resource-based imports [!652, Evan Welsh]
* overrides/GLib: Guard Error.new_literal against invalid domains [!654,
Florian Müllner]
Version 1.68.2
--------------
- Crash and regression fixes backported from the development branch.
- Build fix to adjust to GLib renaming its main branch.
- Closed bugs and merge requests:
* Fix crash in ByteArray.fromGBytes / ByteArray.fromString with 0-length input
[!628, Philip Chimento]
* subprojects: Use GLib main branch [!633, Philip Withnall]
* Construct-only properties and GTK Builder. [#422, !635, Carlos Garnacho]
* Data corruption when passing a 0-terminated array of GVariant [#269, !636,
Evan Welsh]
* Fix race condition in dynamic module resolution. [!641, Evan Welsh]
* Ensure the correct realm is entered in the async executor [!644, Evan Welsh]
* Assertion failure in toggle refs with debug mozjs [#416, !646, Evan Welsh]
Version 1.68.1
--------------
......@@ -33,7 +65,7 @@ Version 1.68.1
Marco Trevisan]
* testFundamental: Add more tests ensuring we properly handle subtypes [!602,
Marco Trevisan]
* Some simple Visual Studio fixes for master [!612, Chun-wei Fan]
* Some simple Visual Studio fixes for main [!612, Chun-wei Fan]
* Using GFileMonitor crashes GNOME Shell with toggling down object error
[#297, !613, !617, Marco Trevisan]
* Deadlock on toggle queue due to GWeakRef [#404, !613, !617, Marco Trevisan]
......
......@@ -1024,8 +1024,12 @@ bool BoxedInstance::init_from_c_struct(JSContext* cx, void* gboxed) {
copy_boxed(gboxed);
return true;
} else if (gtype() == G_TYPE_VARIANT) {
own_ptr(g_variant_ref_sink(static_cast<GVariant*>(gboxed)));
debug_lifecycle("Boxed pointer created by sinking GVariant ref");
// Sink the reference if it is floating
GVariant* temp = g_variant_take_ref(static_cast<GVariant*>(gboxed));
// Add an additional reference which will be unref-ed
// in the marshaller
own_ptr(g_variant_ref(temp));
debug_lifecycle("Boxed pointer created by taking GVariant ref");
return true;
} else if (get_prototype()->can_allocate_directly()) {
copy_memory(gboxed);
......
......@@ -58,31 +58,34 @@ static bool jsobj_set_gproperty(JSContext* cx, JS::HandleObject object,
if (pspec->flags & G_PARAM_CONSTRUCT_ONLY) {
unsigned flags = GJS_MODULE_PROP_FLAGS | JSPROP_READONLY;
GjsAutoChar camel_name = gjs_hyphen_to_camel(pspec->name);
JS::Rooted<JS::PropertyDescriptor> jsprop(cx);
// Ensure to call any associated setter method
if (!g_str_equal(underscore_name.get(), pspec->name)) {
if (!JS_GetPropertyDescriptor(cx, object, underscore_name, &jsprop))
if (g_param_spec_get_qdata(pspec, ObjectBase::custom_property_quark())) {
JS::Rooted<JS::PropertyDescriptor> jsprop(cx);
// Ensure to call any associated setter method
if (!g_str_equal(underscore_name.get(), pspec->name)) {
if (!JS_GetPropertyDescriptor(cx, object, underscore_name, &jsprop))
return false;
if (jsprop.setter() &&
!JS_SetProperty(cx, object, underscore_name, jsvalue))
return false;
}
if (!g_str_equal(camel_name.get(), pspec->name)) {
if (!JS_GetPropertyDescriptor(cx, object, camel_name, &jsprop))
return false;
if (jsprop.setter() &&
!JS_SetProperty(cx, object, camel_name, jsvalue))
return false;
}
if (!JS_GetPropertyDescriptor(cx, object, pspec->name, &jsprop))
return false;
if (jsprop.setter() &&
!JS_SetProperty(cx, object, underscore_name, jsvalue))
!JS_SetProperty(cx, object, pspec->name, jsvalue))
return false;
}
if (!g_str_equal(camel_name.get(), pspec->name)) {
if (!JS_GetPropertyDescriptor(cx, object, camel_name, &jsprop))
return false;
if (jsprop.setter() &&
!JS_SetProperty(cx, object, camel_name, jsvalue))
return false;
}
if (!JS_GetPropertyDescriptor(cx, object, pspec->name, &jsprop))
return false;
if (jsprop.setter() &&
!JS_SetProperty(cx, object, pspec->name, jsvalue))
return false;
return JS_DefineProperty(cx, object, underscore_name, jsvalue, flags) &&
JS_DefineProperty(cx, object, camel_name, jsvalue, flags) &&
JS_DefineProperty(cx, object, pspec->name, jsvalue, flags);
......
......@@ -13,6 +13,7 @@
#include <limits>
#include <string>
#include <tuple> // for tie
#include <unordered_set>
#include <utility> // for move
#include <vector>
......@@ -27,6 +28,7 @@
#include <js/ComparisonOperators.h>
#include <js/GCAPI.h> // for JS_AddWeakPointerCompartmentCallback
#include <js/GCVector.h> // for MutableWrappedPtrOperations
#include <js/HeapAPI.h>
#include <js/MemoryFunctions.h> // for AddAssociatedMemory, RemoveAssoci...
#include <js/PropertyDescriptor.h> // for JSPROP_PERMANENT, JSPROP_READONLY
#include <js/TypeDecls.h>
......@@ -1051,6 +1053,7 @@ bool ObjectPrototype::props_to_g_parameters(JSContext* context,
JS::RootedId prop_id(context);
JS::RootedValue value(context);
JS::Rooted<JS::IdVector> ids(context, context);
std::unordered_set<GParamSpec*> visited_params;
if (!JS_Enumerate(context, props, &ids)) {
gjs_throw(context, "Failed to create property iterator for object props hash");
return false;
......@@ -1072,6 +1075,10 @@ bool ObjectPrototype::props_to_g_parameters(JSContext* context,
if (!param_spec)
return false;
if (visited_params.find(param_spec) != visited_params.end())
continue;
visited_params.insert(param_spec);
if (!JS_GetPropertyById(context, props, prop_id, &value))
return false;
if (value.isUndefined()) {
......@@ -1348,7 +1355,8 @@ void ObjectInstance::wrapped_gobj_toggle_notify(void* instance, GObject*,
* The JSObject associated with the gobject is not rooted,
* but it needs to be. We'll root it.
*/
if (is_main_thread && !anything_queued) {
if (is_main_thread && !anything_queued &&
!JS::RuntimeHeapIsCollecting()) {
self->toggle_up();
} else {
toggle_queue->enqueue(self, ToggleQueue::UP, toggle_handler);
......
......@@ -214,6 +214,13 @@ to_gbytes_func(JSContext *context,
return true;
}
GJS_JSAPI_RETURN_CONVENTION
static bool define_legacy_tostring(JSContext* cx, JS::HandleObject array) {
const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
return JS_DefineFunctionById(cx, array, atoms.to_string(),
instance_to_string_func, 1, 0);
}
/* fromString() function implementation */
GJS_JSAPI_RETURN_CONVENTION
static bool
......@@ -289,6 +296,16 @@ from_string_func(JSContext *context,
if (!encoded)
return gjs_throw_gerror_message(context, error); // frees GError
if (bytes_written == 0) {
g_free(encoded);
JS::RootedObject empty_array(context, JS_NewUint8Array(context, 0));
if (!empty_array || !define_legacy_tostring(context, empty_array))
return false;
argv.rval().setObject(*empty_array);
return true;
}
array_buffer =
JS::NewExternalArrayBuffer(context, bytes_written, encoded,
gfree_arraybuffer_contents, nullptr);
......@@ -297,10 +314,7 @@ from_string_func(JSContext *context,
if (!array_buffer)
return false;
obj = JS_NewUint8ArrayWithBuffer(context, array_buffer, 0, -1);
const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
if (!JS_DefineFunctionById(context, obj, atoms.to_string(),
instance_to_string_func, 1, 0))
if (!obj || !define_legacy_tostring(context, obj))
return false;
argv.rval().setObject(*obj);
......@@ -330,6 +344,15 @@ from_gbytes_func(JSContext *context,
size_t len;
const void* data = g_bytes_get_data(gbytes, &len);
if (len == 0) {
JS::RootedObject empty_array(context, JS_NewUint8Array(context, 0));
if (!empty_array || !define_legacy_tostring(context, empty_array))
return false;
argv.rval().setObject(*empty_array);
return true;
}
JS::RootedObject array_buffer(
context,
JS::NewExternalArrayBuffer(
......@@ -342,12 +365,7 @@ from_gbytes_func(JSContext *context,
JS::RootedObject obj(
context, JS_NewUint8ArrayWithBuffer(context, array_buffer, 0, -1));
if (!obj)
return false;
const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
if (!JS_DefineFunctionById(context, obj, atoms.to_string(),
instance_to_string_func, 1, 0))
if (!obj || !define_legacy_tostring(context, obj))
return false;
argv.rval().setObject(*obj);
......
......@@ -328,7 +328,7 @@ import_module_init(JSContext *context,
GJS_JSAPI_RETURN_CONVENTION
static JSObject* load_module_init(JSContext* cx, JS::HandleObject in_object,
const char* full_path) {
GFile* file) {
bool found;
const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
......@@ -343,8 +343,9 @@ static JSObject* load_module_init(JSContext* cx, JS::HandleObject in_object,
if (v_module.isObject())
return &v_module.toObject();
GjsAutoChar full_path = g_file_get_parse_name(file);
gjs_throw(cx, "Unexpected non-object module __init__ imported from %s",
full_path);
full_path.get());
return nullptr;
}
......@@ -352,7 +353,6 @@ static JSObject* load_module_init(JSContext* cx, JS::HandleObject in_object,
if (!module_obj)
return nullptr;
GjsAutoUnref<GFile> file = g_file_new_for_commandline_arg(full_path);
if (!import_module_init(cx, file, module_obj)) {
JS_ClearPendingException(cx);
return module_obj;
......@@ -368,8 +368,8 @@ static JSObject* load_module_init(JSContext* cx, JS::HandleObject in_object,
GJS_JSAPI_RETURN_CONVENTION
static bool load_module_elements(JSContext* cx, JS::HandleObject in_object,
JS::MutableHandleIdVector prop_ids,
const char* init_path) {
JS::RootedObject module_obj(cx, load_module_init(cx, in_object, init_path));
GFile* file) {
JS::RootedObject module_obj(cx, load_module_init(cx, in_object, file));
if (!module_obj)
return false;
......@@ -389,18 +389,14 @@ static bool load_module_elements(JSContext* cx, JS::HandleObject in_object,
* the value at *result. If found, returns true and sets *result = true.
*/
GJS_JSAPI_RETURN_CONVENTION
static bool
import_symbol_from_init_js(JSContext *cx,
JS::HandleObject importer,
const char *dirname,
const char *name,
bool *result)
{
static bool import_symbol_from_init_js(JSContext* cx, JS::HandleObject importer,
GFile* directory, const char* name,
bool* result) {
bool found;
GjsAutoChar full_path = g_build_filename(dirname, MODULE_INIT_FILENAME,
NULL);
GjsAutoUnref<GFile> file =
g_file_get_child(directory, MODULE_INIT_FILENAME);
JS::RootedObject module_obj(cx, load_module_init(cx, importer, full_path));
JS::RootedObject module_obj(cx, load_module_init(cx, importer, file));
if (!module_obj || !JS_AlreadyHasOwnProperty(cx, module_obj, name, &found))
return false;
......@@ -533,20 +529,23 @@ static bool do_import(JSContext* context, JS::HandleObject obj,
if (dirname[0] == '\0')
continue;
GjsAutoUnref<GFile> directory =
g_file_new_for_commandline_arg(dirname.get());
/* Try importing __init__.js and loading the symbol from it */
bool found = false;
if (!import_symbol_from_init_js(context, obj, dirname.get(), name.get(),
if (!import_symbol_from_init_js(context, obj, directory, name.get(),
&found))
return false;
if (found)
return true;
/* Second try importing a directory (a sub-importer) */
GjsAutoChar full_path =
g_build_filename(dirname.get(), name.get(), nullptr);
GjsAutoUnref<GFile> gfile = g_file_new_for_commandline_arg(full_path);
GjsAutoUnref<GFile> file = g_file_get_child(directory, name.get());
if (g_file_query_file_type(gfile, (GFileQueryInfoFlags) 0, NULL) == G_FILE_TYPE_DIRECTORY) {
if (g_file_query_file_type(file, GFileQueryInfoFlags(0), nullptr) ==
G_FILE_TYPE_DIRECTORY) {
GjsAutoChar full_path = g_file_get_parse_name(file);
gjs_debug(GJS_DEBUG_IMPORTER,
"Adding directory '%s' to child importer '%s'",
full_path.get(), name.get());
......@@ -563,17 +562,18 @@ static bool do_import(JSContext* context, JS::HandleObject obj,
continue;
/* Third, if it's not a directory, try importing a file */
full_path = g_build_filename(dirname.get(), filename.get(), nullptr);
gfile = g_file_new_for_commandline_arg(full_path);
exists = g_file_query_exists(gfile, NULL);
file = g_file_get_child(directory, filename.get());
exists = g_file_query_exists(file, nullptr);
if (!exists) {
gjs_debug(GJS_DEBUG_IMPORTER, "JS import '%s' not found in %s",
name.get(), dirname.get());
GjsAutoChar full_path = g_file_get_parse_name(file);
gjs_debug(GJS_DEBUG_IMPORTER,
"JS import '%s' not found in %s at %s", name.get(),
dirname.get(), full_path.get());
continue;
}
if (import_file_on_module(context, obj, id, name.get(), gfile)) {
if (import_file_on_module(context, obj, id, name.get(), file)) {
gjs_debug(GJS_DEBUG_IMPORTER, "successfully imported module '%s'",
name.get());
return true;
......@@ -632,8 +632,6 @@ static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
JS::RootedValue elem(context);
JS::RootedString str(context);
for (i = 0; i < search_path_len; ++i) {
char *init_path;
elem.setUndefined();
if (!JS_GetElement(context, search_path, i, &elem)) {
/* this means there was an exception, while elem.isUndefined()
......@@ -655,19 +653,18 @@ static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
if (!dirname)
return false;
init_path =
g_build_filename(dirname.get(), MODULE_INIT_FILENAME, nullptr);
GjsAutoUnref<GFile> directory =
g_file_new_for_commandline_arg(dirname.get());
GjsAutoUnref<GFile> file =
g_file_get_child(directory, MODULE_INIT_FILENAME);
if (!load_module_elements(context, object, properties, init_path))
if (!load_module_elements(context, object, properties, file))
return false;
g_free(init_path);
/* new_for_commandline_arg handles resource:/// paths */
GjsAutoUnref<GFile> dir = g_file_new_for_commandline_arg(dirname.get());
GjsAutoUnref<GFileEnumerator> direnum =
g_file_enumerate_children(dir, "standard::name,standard::type",
G_FILE_QUERY_INFO_NONE, NULL, NULL);
GjsAutoUnref<GFileEnumerator> direnum = g_file_enumerate_children(
directory, "standard::name,standard::type", G_FILE_QUERY_INFO_NONE,
nullptr, nullptr);
while (true) {
GFileInfo *info;
......
......@@ -525,6 +525,8 @@ class PromiseData {
static void load_async_callback(GObject* file, GAsyncResult* res, void* data) {
std::unique_ptr<PromiseData> promise(PromiseData::from_ptr(data));
JSAutoRealm ac(promise->cx, gjs_get_import_global(promise->cx));
char* contents;
size_t length;
GError* error = nullptr;
......
......@@ -15,8 +15,33 @@ minijasmine = executable('minijasmine', '../minijasmine.cpp',
include_directories: top_include,
install: get_option('installed_tests'), install_dir: installed_tests_execdir)
gidatadir = gi.get_pkgconfig_variable('gidatadir')
gi_tests = gidatadir / 'tests'
# When building gobject-introspection as a subproject, use the variables
# exported by the subproject to find the locations of the test sources.
# Otherwise, get the locations from the pkgconfig file.
#
# The subproject does not yet export variables for warnlib's sources.
# See https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/287
skip_warnlib = false
if gi.type_name() == 'internal'
gi_subproject = subproject('gobject-introspection')
regress_sources = (gi_subproject.get_variable('test_regress_sources') +
gi_subproject.get_variable('test_regress_headers'))
gimarshallingtests_sources = (
gi_subproject.get_variable('test_marshalling_sources') +
gi_subproject.get_variable('test_marshalling_headers'))
gi_tests_include = gi_subproject.get_variable('test_regress_incdirs')
skip_warnlib = true
else
gidatadir = gi.get_pkgconfig_variable('gidatadir')
gi_tests = gidatadir / 'tests'
regress_sources = [gi_tests / 'regress.c', gi_tests / 'regress.h']
warnlib_sources = [gi_tests / 'warnlib.c', gi_tests / 'warnlib.h']
gimarshallingtests_sources = [
gi_tests / 'gimarshallingtests.c',
gi_tests / 'gimarshallingtests.h',
]
gi_tests_include = include_directories(gi_tests)
endif
test_gir_extra_c_args = []
test_gir_warning_c_args = []
......@@ -40,12 +65,9 @@ else
regress_gir_c_args += ['-D_GI_DISABLE_CAIRO']
endif
regress_sources = [
gi_tests / 'regress.c',
gi_tests / 'regress.h',
]
libregress = library('regress', regress_sources,
c_args: regress_gir_c_args + test_gir_warning_c_args,
include_directories: gi_tests_include,
dependencies: regress_dependencies, install: get_option('installed_tests'),
install_dir: installed_tests_execdir)
regress_gir = gnome.generate_gir(libregress, includes: regress_gir_includes,
......@@ -56,29 +78,27 @@ regress_gir = gnome.generate_gir(libregress, includes: regress_gir_includes,
install_dir_typelib: installed_tests_execdir)
regress_typelib = regress_gir[1]
warnlib_sources = [
gi_tests / 'warnlib.c',
gi_tests / 'warnlib.h',
]
libwarnlib = library('warnlib', warnlib_sources,
c_args: test_gir_warning_c_args + test_gir_extra_c_args,
dependencies: [glib, gobject, gio], install: get_option('installed_tests'),
install_dir: installed_tests_execdir)
# This should have --warn-all turned off, but there is currently no way to do so
# in gnome.generate_gir(). See https://github.com/mesonbuild/meson/issues/5876
warnlib_gir = gnome.generate_gir(libwarnlib, includes: ['Gio-2.0'],
sources: warnlib_sources, namespace: 'WarnLib', nsversion: '1.0',
symbol_prefix: 'warnlib_', header: 'warnlib.h',
install: get_option('installed_tests'), install_dir_gir: false,
install_dir_typelib: installed_tests_execdir)
warnlib_typelib = warnlib_gir[1]
if not skip_warnlib
libwarnlib = library('warnlib', warnlib_sources,
c_args: test_gir_warning_c_args + test_gir_extra_c_args,
include_directories: gi_tests_include,
dependencies: [glib, gobject, gio],
install: get_option('installed_tests'),
install_dir: installed_tests_execdir)
# This should have --warn-all turned off, but there is currently no way to
# do so in gnome.generate_gir().
# See https://github.com/mesonbuild/meson/issues/5876
warnlib_gir = gnome.generate_gir(libwarnlib, includes: ['Gio-2.0'],
sources: warnlib_sources, namespace: 'WarnLib', nsversion: '1.0',
symbol_prefix: 'warnlib_', header: 'warnlib.h',
install: get_option('installed_tests'), install_dir_gir: false,
install_dir_typelib: installed_tests_execdir)
warnlib_typelib = warnlib_gir[1]
endif
gimarshallingtests_sources = [
gi_tests / 'gimarshallingtests.c',
gi_tests / 'gimarshallingtests.h',
]
libgimarshallingtests = library('gimarshallingtests',
gimarshallingtests_sources, dependencies: [glib, gobject, gio],
include_directories: gi_tests_include,
c_args: test_gir_extra_c_args + test_gir_warning_c_args,
install: get_option('installed_tests'), install_dir: installed_tests_execdir)
gimarshallingtests_gir = gnome.generate_gir(libgimarshallingtests,
......@@ -121,7 +141,6 @@ jasmine_tests = [
'Signals',
'System',
'Tweener',
'WarnLib',
]
if build_cairo
......@@ -145,17 +164,22 @@ installed_js_tests_dir = installed_tests_execdir / 'js'
gschemas_compiled = gnome.compile_schemas(
depend_files: 'org.gnome.GjsTest.gschema.xml')
tests_dependencies = [
gschemas_compiled,
gjstest_tools_typelib,
gimarshallingtests_typelib,
regress_typelib,
]
if not skip_warnlib
jasmine_tests += 'WarnLib'
tests_dependencies += warnlib_typelib
endif
foreach test : jasmine_tests
test_file = files('test@0@.js'.format(test))
test(test, minijasmine, args: test_file,
depends: [
gschemas_compiled,
gjstest_tools_typelib,
gimarshallingtests_typelib,
regress_typelib,
warnlib_typelib,
],
test(test, minijasmine, args: test_file, depends: tests_dependencies,
env: tests_environment, protocol: 'tap', suite: 'JS')
test_description_subst = {
......
......@@ -68,6 +68,16 @@ describe('Byte array', function () {
expect(ByteArray.toGBytes(a).get_size()).toEqual(0);
});
it('deals gracefully with a 0-length GLib.Bytes', function () {
const noBytes = ByteArray.toGBytes(new Uint8Array(0));
expect(ByteArray.fromGBytes(noBytes).length).toEqual(0);
});
it('deals gracefully with a 0-length string', function () {
expect(ByteArray.fromString('').length).toEqual(0);
expect(ByteArray.fromString('', 'LATIN1').length).toEqual(0);
});
it('deals gracefully with a non Uint8Array', function () {
const a = [97, 98, 99, 100, 0];
expect(() => ByteArray.toString(a)).toThrow();
......
......@@ -206,16 +206,16 @@ describe('thrown GError', function () {
});
});
describe('Returned GError', function () {
it('can be nullable', function () {
// expect a critical about passing in an invalid error domain, but this
// should not crash or log a critical about freeing a null GError
GLib.test_expect_message('GLib', GLib.LogLevelFlags.LEVEL_CRITICAL,
"g_error_new_literal: assertion 'domain != 0' failed");
expect(GLib.Error.new_literal(0, 0, 'message')).toBeNull();
GLib.test_assert_expected_messages_internal('GLib', 'testExceptions.js',
0, 'testGErrorMessages');
describe('GError.new_literal', function () {
it('constructs a valid GLib.Error', function () {
const e = GLib.Error.new_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED, 'message');
expect(e instanceof GLib.Error).toBeTruthy();
expect(e.code).toEqual(Gio.IOErrorEnum.FAILED);
expect(e.message).toEqual('message');
});
it('does not accept invalid domains', function () {
expect(() => GLib.Error.new_literal(0, 0, 'message'))
.toThrowError(/0 is not a valid domain/);
});
});
......@@ -514,11 +514,11 @@ describe('Zero-terminated C array', function () {
});
['none', 'container', 'full'].forEach(transfer => {
xit(`marshals as a transfer-${transfer} in and out parameter`, function () {
it(`marshals as a transfer-${transfer} in and out parameter`, function () {
const returnedArray =
GIMarshallingTests[`array_gvariant_${transfer}_in`](variantArray);
expect(returnedArray.map(v => v.deepUnpack())).toEqual([27, 'Hello']);
}).pend('https://gitlab.gnome.org/GNOME/gjs/issues/269');
});
});
});
});
......
......@@ -2,7 +2,7 @@
# SPDX-FileCopyrightText: 2019 Philip Chimento <philip.chimento@gmail.com>
# SPDX-FileCopyrightText: 2019 Chun-wei Fan <fanchunwei@src.gnome.org>
project('gjs', 'cpp', 'c', version: '1.68.1', license: ['MIT', 'LGPL2+'],
project('gjs', 'cpp', 'c', version: '1.68.3', license: ['MIT', 'LGPL2+'],
meson_version: '>= 0.52.0',
default_options: ['cpp_std=c++17', 'cpp_rtti=false', 'c_std=c99',
'warning_level=2'])
......@@ -638,8 +638,9 @@ valgrind_environment.set('G_DEBUG',
'fatal-warnings,fatal-criticals,gc-friendly')
valgrind_environment.set('VALGRIND', 'valgrind')
glib_suppresssions = (glib.get_pkgconfig_variable('prefix') / 'share' /
'glib-2.0' / 'valgrind' / 'glib.supp')
glib_prefix = glib.get_variable(pkgconfig: 'prefix', default_value: '/usr')
glib_suppresssions = (glib_prefix / 'share' / 'glib-2.0' / 'valgrind' /
'glib.supp')
gjs_suppressions = (meson.current_source_dir() / 'installed-tests' / 'extra' /
'gjs.supp')
valgrind_args = [
......
......@@ -275,6 +275,16 @@ function _init() {
return false;
};
// Guard against domains that aren't valid quarks and would lead
// to a crash
const quarkToString = this.quark_to_string;
const realNewLiteral = this.Error.new_literal;
this.Error.new_literal = function (domain, code, message) {
if (quarkToString(domain) === null)
throw new TypeError(`Error.new_literal: ${domain} is not a valid domain`);
return realNewLiteral(domain, code, message);
};
this.Variant._new_internal = function (sig, value) {
let signature = Array.prototype.slice.call(sig);
......
......@@ -161,6 +161,11 @@ class ModuleLoader extends InternalModuleLoader {
if (!result)
return null;
// Check if module loaded while awaiting.
module = registry.get(uri.uri);
if (module)
return module;
const [text, internal = false] = result;
const priv = new ModulePrivate(uri.uri, uri.uri, internal);
......
......@@ -4,5 +4,5 @@
[wrap-git]
directory=glib
url=https://gitlab.gnome.org/GNOME/glib.git
revision=master
revision=main
depth=1