diff -Nru gjs-1.74.0/build/flatpak/org.gnome.GjsConsole.json gjs-1.72.2/build/flatpak/org.gnome.GjsConsole.json --- gjs-1.74.0/build/flatpak/org.gnome.GjsConsole.json 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/build/flatpak/org.gnome.GjsConsole.json 2022-08-08 05:05:12.000000000 +0000 @@ -11,16 +11,10 @@ "sdk": "org.gnome.Sdk", "command": "gjs-console", "finish-args": [ - "--share=ipc", - "--socket=fallback-x11", + "--socket=x11", "--socket=wayland", - "--device=dri", "--share=network", - "--filesystem=host", - "--filesystem=home", - "--socket=session-bus", - "--socket=system-bus", - "--socket=pulseaudio" + "--filesystem=host" ], "modules": [ { diff -Nru gjs-1.74.0/debian/changelog gjs-1.72.2/debian/changelog --- gjs-1.74.0/debian/changelog 2022-10-17 18:16:23.000000000 +0000 +++ gjs-1.72.2/debian/changelog 2023-05-19 11:12:55.000000000 +0000 @@ -1,10 +1,9 @@ -gjs (1.74.0-0ubuntu1) jammy-security; urgency=medium +gjs (1.72.2-0ubuntu2) jammy; urgency=medium - * New upstream major release (LP: #1993214) - * Build against mozjs102 - * debian/libgjs0g.symbols: Add new symbol + [ Daniel van Vugt ] + * Add context-Clear-all-vectors-of-JS-Heap-on-dispose.patch (LP: #1974293) - -- Jeremy Bicha Mon, 17 Oct 2022 14:16:23 -0400 + -- Ghadi Elie Rahme Fri, 19 May 2023 11:12:55 +0000 gjs (1.72.2-0ubuntu1) jammy; urgency=medium diff -Nru gjs-1.74.0/debian/control gjs-1.72.2/debian/control --- gjs-1.74.0/debian/control 2022-10-17 18:16:23.000000000 +0000 +++ gjs-1.72.2/debian/control 2022-08-10 16:26:00.000000000 +0000 @@ -18,7 +18,7 @@ libgirepository1.0-dev (>= 1.64), gir1.2-gtk-3.0, gobject-introspection (>= 1.64), - libmozjs-102-dev, + libmozjs-91-dev (>= 91.3.0), libreadline-dev, meson (>= 0.50.0), dbus , @@ -92,7 +92,7 @@ libgjs0g (= ${binary:Version}), libgirepository1.0-dev (>= 1.64), libcairo2-dev, - libmozjs-102-dev, + libmozjs-91-dev (>= 91.3.0), Description: Mozilla-based javascript bindings for the GNOME platform Makes it possible for applications to use all of GNOME's platform libraries using the JavaScript language. It's mainly based on the diff -Nru gjs-1.74.0/debian/control.in gjs-1.72.2/debian/control.in --- gjs-1.74.0/debian/control.in 2022-10-17 18:16:23.000000000 +0000 +++ gjs-1.72.2/debian/control.in 2022-08-10 16:26:00.000000000 +0000 @@ -14,7 +14,7 @@ libgirepository1.0-dev (>= 1.64), gir1.2-gtk-3.0, gobject-introspection (>= 1.64), - libmozjs-102-dev, + libmozjs-91-dev (>= 91.3.0), libreadline-dev, meson (>= 0.50.0), dbus , @@ -88,7 +88,7 @@ libgjs0g (= ${binary:Version}), libgirepository1.0-dev (>= 1.64), libcairo2-dev, - libmozjs-102-dev, + libmozjs-91-dev (>= 91.3.0), Description: Mozilla-based javascript bindings for the GNOME platform Makes it possible for applications to use all of GNOME's platform libraries using the JavaScript language. It's mainly based on the diff -Nru gjs-1.74.0/debian/libgjs0g.symbols gjs-1.72.2/debian/libgjs0g.symbols --- gjs-1.74.0/debian/libgjs0g.symbols 2022-10-17 18:16:23.000000000 +0000 +++ gjs-1.72.2/debian/libgjs0g.symbols 2022-08-10 16:26:00.000000000 +0000 @@ -36,7 +36,6 @@ gjs_dumpstack@Base 1.63.90 gjs_error_quark@Base 1.63.90 gjs_format_int_alternative_output@Base 1.63.90 - gjs_g_binding_group_bind_full@Base 1.73.2 gjs_g_object_bind_property_full@Base 1.70.0 gjs_get_js_version@Base 1.63.90 gjs_gobject_class_info@Base 1.70.0 diff -Nru gjs-1.74.0/debian/patches/context-Clear-all-vectors-of-JS-Heap-on-dispose.patch gjs-1.72.2/debian/patches/context-Clear-all-vectors-of-JS-Heap-on-dispose.patch --- gjs-1.74.0/debian/patches/context-Clear-all-vectors-of-JS-Heap-on-dispose.patch 1970-01-01 00:00:00.000000000 +0000 +++ gjs-1.72.2/debian/patches/context-Clear-all-vectors-of-JS-Heap-on-dispose.patch 2023-05-19 11:12:55.000000000 +0000 @@ -0,0 +1,32 @@ +From: Daniel van Vugt +Date: Wed, 5 Apr 2023 17:48:22 +0800 +Subject: context: Clear all vectors of JS::Heap on dispose + +Otherwise we might still have some `JS::Heap`s lingering after +`JS_DestroyContext`, which will fail to destruct (crash) when their +destructors are called later in `~GjsContextPrivate()`. + +Fixes: https://gitlab.gnome.org/GNOME/gjs/-/issues/472 + +Bug-Ubuntu: https://launchpad.net/bugs/1974293 +Origin: backport, https://gitlab.gnome.org/GNOME/gjs/-/merge_requests/834 +Forwarded: yes +Last-Update: 2023-04-11 +--- + gjs/context.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/gjs/context.cpp b/gjs/context.cpp + +--- a/gjs/context.cpp ++++ b/gjs/context.cpp +@@ -417,6 +417,9 @@ + void GjsContextPrivate::dispose(void) { + if (m_cx) { + stop_draining_job_queue(); ++ m_job_queue.clear(); ++ ++ m_object_init_list.clear(); + + gjs_debug(GJS_DEBUG_CONTEXT, + "Notifying reference holders of GjsContext dispose"); diff -Nru gjs-1.74.0/debian/patches/series gjs-1.72.2/debian/patches/series --- gjs-1.74.0/debian/patches/series 2022-10-17 18:16:23.000000000 +0000 +++ gjs-1.72.2/debian/patches/series 2023-05-19 11:12:55.000000000 +0000 @@ -0,0 +1 @@ +context-Clear-all-vectors-of-JS-Heap-on-dispose.patch diff -Nru gjs-1.74.0/doc/ByteArray.md gjs-1.72.2/doc/ByteArray.md --- gjs-1.74.0/doc/ByteArray.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/ByteArray.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,117 +1,43 @@ -# ByteArray +The `imports.byteArray` module was originally based on an +ECMAScript 4 proposal that was never adopted. +Now that ES6 has typed arrays, we use `Uint8Array` to represent byte +arrays in GJS and add some extra functions for conversion to and from +strings and `GLib.Bytes`. + +Unlike the old custom `ByteArray`, `Uint8Array` is not resizable. The main +goal for most gjs users will be to shovel bytes between various C +APIs, for example reading from an IO stream and then pushing the bytes +into a parser. Actually manipulating bytes in JS is likely to be +pretty rare, and slow ... an advantage of the +gjs/gobject-introspection setup is that stuff best done in C, like +messing with bytes, can be done in C. -The `ByteArray` module provides a number of utilities for converting between -[`GLib.Bytes`][gbytes] object, `String` values and `Uint8Array` objects. +--- -It was originally based on an ECMAScript 4 proposal that was never adopted, but -now that ES6 has typed arrays, we use the standard `Uint8Array` to represent -byte arrays in GJS. +## ByteArray Functions ## -The primary use for most GJS users will be to exchange bytes between various C -APIs, like reading from an IO stream and then pushing the bytes into a parser. -Actually manipulating bytes in GJS is likely to be pretty slow and fortunately -rarely necessary. An advantage of the GJS and GObject-Introspection setup is -that most of the tasks best done in C, like messing with bytes, can be. +The ByteArray module has the following functions: -[gbytes]: https://gjs-docs.gnome.org/glib20/glib.bytes - -#### Import - -> Attention: This module is not available as an ECMAScript Module - -The `ByteArray` module is available on the global `imports` object: - -```js -const ByteArray = imports.byteArray; -``` - -### ByteArray.fromString(string, encoding) - -> Deprecated: Use [`TextEncoder.encode()`][textencoder-encode] instead - -Type: -* Static - -Parameters: -* string (`String`) — A string to encode -* encoding (`String`) — Optional encoding of `string` - -Returns: -* (`Uint8Array`) — A byte array +### `fromString(s:String, encoding:String):Uint8Array` ### Convert a String into a newly constructed `Uint8Array`; this creates a new `Uint8Array` of the same length as the String, then assigns each `Uint8Array` entry the corresponding byte value of the String encoded according to the given encoding (or UTF-8 if not given). -[textencoder-encode]: https://gjs-docs.gnome.org/gjs/encoding.md#textencoder-encode - -### ByteArray.toString(byteArray, encoding) - -> Deprecated: Use [`TextDecoder.decode()`][textdecoder-decode] instead - -Type: -* Static - -Parameters: -* byteArray (`Uint8Array`) — A byte array to decode -* encoding (`String`) — Optional encoding of `byteArray` - -Returns: -* (`String`) — A string +### `toString(a:Uint8Array, encoding:String):String` ### Converts the `Uint8Array` into a literal string. The bytes are interpreted according to the given encoding (or UTF-8 if not given). -The resulting string is guaranteed to round-trip back into an identical -ByteArray by passing the result to `ByteArray.fromString()`. In other words, -this check is guaranteed to pass: - -```js -const original = ByteArray.fromString('foobar'); -const copy = ByteArray.fromString(ByteArray.toString(original)); +The resulting string is guaranteed to round-trip back into an identical ByteArray by passing the result to `ByteArray.fromString()`, i.e., `b === ByteArray.fromString(ByteArray.toString(b, encoding), encoding)`. -console.assert(original.every((value, index) => value === copy[index])); -``` - -[textdecoder-decode]: https://gjs-docs.gnome.org/gjs/encoding.md#textdecoder-decode - -### ByteArray.fromGBytes(bytes) - -> Deprecated: Use [`GLib.Bytes.toArray()`][gbytes-toarray] instead - -Type: -* Static - -Parameters: -* bytes (`GLib.Bytes`) — A [`GLib.Bytes`][gbytes] to convert - -Returns: -* (`Uint8Array`) — A new byte array - -Convert a [`GLib.Bytes`][gbytes] instance into a newly constructed `Uint8Array`. +### `fromGBytes(b:GLib.Bytes):Uint8Array` ### +Convert a `GLib.Bytes` instance into a newly constructed `Uint8Array`. The contents are copied. -[gbytes]: https://gjs-docs.gnome.org/glib20/glib.bytes -[gbytes-toarray]: https://gjs-docs.gnome.org/gjs/overrides.md#glib-bytes-toarray - -### ByteArray.toGBytes(byteArray) - -> Deprecated: Use [`new GLib.Bytes()`][gbytes] instead - -Type: -* Static - -Parameters: -* byteArray (`Uint8Array`) — A byte array to convert - -Returns: -* (`GLib.Bytes`) — A new [`GLib.Bytes`][gbytes] - -Converts the `Uint8Array` into a [`GLib.Bytes`][gbytes] instance. +### `toGBytes(a:Uint8Array):GLib.Bytes` ### +Converts the `Uint8Array` into a `GLib.Bytes` instance. The contents are copied. - -[gbytes]: https://gjs-docs.gnome.org/glib20/glib.bytes - diff -Nru gjs-1.74.0/doc/cairo.md gjs-1.72.2/doc/cairo.md --- gjs-1.74.0/doc/cairo.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/cairo.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,46 +1,43 @@ -# Cairo +The cairo bindings follows the C API pretty closely. -The `Cairo` module is a set of custom bindings for the [cairo][cairo] 2D -graphics library. Cairo is used by GTK, Clutter, Mutter and others for drawing -shapes, text, compositing images and performing affine transformations. - -The GJS bindings for cairo follow the C API pretty closely, although some of the -less common functions are not available yet. In spite of this, the bindings are -complete enough that the upstream [cairo documentation][cairo-docs] may be -helpful to those new to using Cairo. - -[cairo]: https://www.cairographics.org/ -[cairo-docs]: https://www.cairographics.org/documentation/ - -#### Import - -When using ESModules: +## Naming ## +The module name is called 'cairo' and usually imported into +the namespace as 'Cairo'. ```js -import Cairo from 'cairo'; +const Cairo = imports.cairo; ``` +Methods are studlyCaps, similar to other JavaScript apis, eg -When using legacy imports: +`cairo_move_to` is wrapped to `Cairo.Context.moveTo()` +`cairo_surface_write_to_png` to `Cairo.Context.writeToPNG()`. -```js -const Cairo = imports.cairo; -``` +Abbreviations such as RGB, RGBA, PNG, PDF, SVG are always +upper-case. -#### Mapping +Enums are set in the cairo namespace, the enum names are capitalized: -Methods are studlyCaps, similar to other JavaScript APIs. Abbreviations such as -RGB, RGBA, PNG, PDF and SVG are always upper-case. For example: +`CAIRO_FORMAT_ARGB32` is mapped to `Cairo.Format.ARGB32` etc. -* `cairo_move_to()` is mapped to `Cairo.Context.moveTo()` -* `cairo_surface_write_to_png()` is mapped to `Cairo.Context.writeToPNG()` +## Surfaces (`cairo_surface_t`) ## -Unlike the methods and structures, Cairo's enumerations are documented -alongside the other GNOME APIs in the [`cairo`][cairo-devdocs] namespace. These -are mapped similar to other libraries in GJS (eg. `Cairo.Format.ARGB32`). +Prototype hierarchy -[cairo-devdocs]: https://gjs-docs.gnome.org/cairo10 +* `Surface` (abstract) + * `ImageSurface` + * `PDFSurface` + * `SVGSurface` + * `PostScriptSurface` -## Cairo.Context (`cairo_t`) +The native surfaces (win32, quartz, xlib) are not supported at this point. + +Methods manipulating a surface are present in the surface class. +Creating an ImageSurface from a PNG is done by calling a static method: +```js +let surface = Cairo.ImageSurface.createFromPNG("filename.png"); +``` + +## Context (`cairo_t`) ## `cairo_t` is mapped as `Cairo.Context`. @@ -52,53 +49,19 @@ let cr = Gdk.cairo_create(...); ``` - All introspection methods taking or returning a `cairo_t` will automatically create a `Cairo.Context`. -### Cairo.Context.$dispose() - -> Attention: This method must be called to avoid leaking memory - -Free a `Cairo.Context` and all associated memory. - -Unlike other objects and values in GJS, the `Cairo.Context` object requires an -explicit free function to avoid memory leaks. However you acquire a instance, -the `Cairo.Context.$dispose()` method must be called when you are done with it. - -For example, when using a [`Gtk.DrawingArea`][gtkdrawingarea]: - -```js -import Cairo from 'cairo'; -import Gtk from 'gi://Gtk?version=4.0'; - -// Initialize GTK -Gtk.init(); - -// Create a drawing area and set a drawing function -const drawingArea = new Gtk.DrawingArea(); - -drawingArea.set_draw_func((area, cr, width, height) => { - // Perform operations on the surface context - - // Freeing the context before returning from the callback - cr.$dispose(); -}); -``` - -[gtkdrawingarea]: https://gjs-docs.gnome.org/gtk40/gtk.drawingarea - - -## Cairo.Pattern (`cairo_pattern_t`) +## Patterns (`cairo_pattern_t`) ## Prototype hierarchy -* `Cairo.Pattern` - * `Cairo.Gradient` - * `Cairo.LinearGradient` - * `Cairo.RadialGradient` - * `Cairo.SurfacePattern` - * `Cairo.SolidPattern` +* `Pattern` + * `Gradient` + * `LinearGradient` + * `RadialGradient` + * `SurfacePattern` + * `SolidPattern` You can create a linear gradient by calling the constructor: @@ -114,32 +77,7 @@ let pattern = new Cairo.SolidPattern.createRGBA(0, 0, 0, 0); ``` - -## Cairo.Surface (`cairo_surface_t`) - -Prototype hierarchy - -* `Cairo.Surface` (abstract) - * `Cairo.ImageSurface` - * `Cairo.PDFSurface` - * `Cairo.SVGSurface` - * `Cairo.PostScriptSurface` - -The native surfaces (win32, quartz, xlib) are not supported at this time. - -Methods manipulating a surface are present in the surface class. For example, -creating a `Cairo.ImageSurface` from a PNG is done by calling a static method: - -```js -const surface = Cairo.ImageSurface.createFromPNG('filename.png'); -``` - -## To-do List - -As previously mentioned, the Cairo bindings for GJS are not entirely complete -and contributions are welcome. Some of the bindings left to be implemented -include: - +TODO: * context: wrap the remaining methods * surface methods * image surface methods @@ -147,13 +85,9 @@ * version * iterating over `cairo_path_t` -Many font and glyph operations are not yet supported, and it is recommended to -use [`PangoCairo`][pango-cairo] as an alternative: - +Fonts & Glyphs are not wrapped, use PangoCairo instead. * glyphs * text cluster * font face * scaled font * font options - -[pango-cairo]: https://gjs-docs.gnome.org/pangocairo10 diff -Nru gjs-1.74.0/doc/Console.md gjs-1.72.2/doc/Console.md --- gjs-1.74.0/doc/Console.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Console.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,314 +0,0 @@ -# Console - -GJS implements the [WHATWG Console][whatwg-console] specification, with some -changes to accommodate GLib. - -In particular, log severity is mapped to [`GLib.LogLevelFlags`][gloglevelflags] -and some methods are not implemented: - -* `console.profile()` -* `console.profileEnd()` -* `console.timeStamp()` - -#### Import - -The functions in this module are available globally, without import. - -[whatwg-console]: https://console.spec.whatwg.org/ -[gloglevelflags]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags - -### console.assert(condition, ...data) - -Type: -* Static - -Parameters: -* condition (`Boolean`) — A boolean condition which, if `false`, causes the log - to print -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Logs a critical message if the condition is not truthy. - -See [`console.error()`](#console-error) for additional information. - -### console.clear() - -Type: -* Static - -> New in GJS 1.70 (GNOME 41) - -Resets grouping and clears the terminal on systems supporting ANSI terminal -control sequences. - -In file-based stdout or systems which do not support clearing, `console.clear()` -has no visual effect. - -### console.count(label) - -Type: -* Static - -Parameters: -* label (`String`) — Optional label - -> New in GJS 1.70 (GNOME 41) - -Logs how many times `console.count()` has been called with the given `label`. - -See [`console.countReset()`](#console-countreset) for resetting a count. - -### console.countReset(label) - -Type: -* Static - -Parameters: -* label (`String`) — The unique label to reset the count for - -> New in GJS 1.70 (GNOME 41) - -Resets a counter used with `console.count()`. - -### console.debug(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Logs a message with severity equal to -[`GLib.LogLevelFlags.LEVEL_DEBUG`][gloglevelflagsdebug]. - -[gloglevelflagsdebug]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_debug - -### console.dir(item, options) - -Type: -* Static - -Parameters: -* item (`Object`) — The item to display -* options (`undefined`) — Additional options for the formatter. Unused in GJS. - -> New in GJS 1.70 (GNOME 41) - -Resurively display all properties of `item`. - -### console.dirxml(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Alias for [`console.log()`](#console-log) - -### console.error(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Logs a message with severity equal to -[`GLib.LogLevelFlags.LEVEL_CRITICAL`][gloglevelflagscritical]. - -Does not use [`GLib.LogLevelFlags.LEVEL_ERROR`][gloglevelflagserror] to avoid -asserting and forcibly shutting down the application. - -[gloglevelflagscritical]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_critical -[gloglevelflagserror]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_error - -### console.group(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Creates a new inline group in the console log, causing any subsequent console -messages to be indented by an additional level, until `console.groupEnd()` is -called. - -### console.groupCollapsed(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Alias for [`console.group()`](#console-group) - -### console.groupEnd() - -Type: -* Static - -> New in GJS 1.70 (GNOME 41) - -Exits the current inline group in the console log. - -### console.info(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Logs a message with severity equal to -[`GLib.LogLevelFlags.LEVEL_INFO`][gloglevelflagsinfo]. - -[gloglevelflagsinfo]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_info - -### console.log(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Logs a message with severity equal to -[`GLib.LogLevelFlags.LEVEL_MESSAGE`][gloglevelflagsmessage]. - -[gloglevelflagsmessage]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_message - -### console.table(tabularData, options) - -> Note: This is an alias for [`console.log()`](#console-log) in GJS - -Type: -* Static - -Parameters: -* tabularData (`Any`) — Formatting substitutions, if applicable -* properties (`undefined`) — Unsupported in GJS - -> New in GJS 1.70 (GNOME 41) - -Logs a message with severity equal to -[`GLib.LogLevelFlags.LEVEL_MESSAGE`][gloglevelflagsmessage]. - -[gloglevelflagsmessage]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_message - -### console.time(label) - -Type: -* Static - -Parameters: -* label (`String`) — unique identifier for this action, pass to - `console.timeEnd()` to complete - -> New in GJS 1.70 (GNOME 41) - -Starts a timer you can use to track how long an operation takes. - -### console.timeEnd(label) - -Type: -* Static - -Parameters: -* label (`String`) — unique identifier for this action - -> New in GJS 1.70 (GNOME 41) - -Logs the time since the last call to `console.time(label)` and completes the -action. - -Call `console.time(label)` again to re-measure. - -### console.timeLog(label, ...data) - -Type: -* Static - -Parameters: -* label (`String`) — unique identifier for this action, pass to - `console.timeEnd()` to complete -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Logs the time since the last call to `console.time(label)` where `label` is the -same. - -### console.trace(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Outputs a stack trace to the console. - -### console.warn(...data) - -Type: -* Static - -Parameters: -* data (`Any`) — Formatting substitutions, if applicable - -> New in GJS 1.70 (GNOME 41) - -Logs a message with severity equal to -[`GLib.LogLevelFlags.LEVEL_WARNING`][gloglevelflagswarning]. - -[gloglevelflagswarning]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_warning - - -## Log Domain - -> New in GJS 1.70 (GNOME 41) - -The log domain for the default global `console` object is set to `"Gjs-Console"` -by default, but can be changed if necessary. The three symbols of interest are -`setConsoleLogDomain()`, `getConsoleLogDomain()` and `DEFAULT_LOG_DOMAIN`. - -You can import these symbols and modify the log domain like so: - -```js -import { setConsoleLogDomain, getConsoleLogDomain, DEFAULT_LOG_DOMAIN } from 'console'; - -// Setting the log domain -setConsoleLogDomain('my.app.id'); - -// expected output: my.app.id-Message: 12:21:17.899: cool -console.log('cool'); - -// Checking and resetting the log domain -if (getConsoleLogDomain() !== DEFAULT_LOG_DOMAIN) - setConsoleLogDomain(DEFAULT_LOG_DOMAIN); - -// expected output: Gjs-Console-Message: 12:21:17.899: cool -console.log('cool'); -``` - diff -Nru gjs-1.74.0/doc/Encoding.md gjs-1.72.2/doc/Encoding.md --- gjs-1.74.0/doc/Encoding.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Encoding.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -# Encoding - -GJS implements the [WHATWG Encoding][whatwg-encoding] specification. - -The `TextDecoder` interface represents a decoder for a specific text encoding, -such as `UTF-8`, `ISO-8859-2`, `KOI8-R`, `GBK`, etc. A decoder takes a list of -bytes as input and emits a list of code points. - -The `TextEncoder` interface takes a list of code points as input and emits a -list of UTF-8 bytes. - -#### Import - -The functions in this module are available globally, without import. - -[whatwg-encoding]: https://encoding.spec.whatwg.org/ - -### TextDecoder(utfLabel, options) - -Type: -* Static - -Parameters: -* utfLabel (`Number`) — Optional string, defaulting to `"utf-8"`, containing the - label of the encoder. -* options (`Object`) — Optional dictionary with the `Boolean` property `fatal`, - corresponding to the `TextDecoder.fatal` property. - -Returns: -* (`TextDecoder`) — A newly created `TextDecoder` object - -> New in GJS 1.70 (GNOME 41) - -The `TextDecoder()` constructor returns a newly created `TextDecoder` object for -the encoding specified in parameter. - -If the value for `utfLabel` is unknown, or is one of the two values leading to a -'replacement' decoding algorithm ("iso-2022-cn" or "iso-2022-cn-ext"), a -`RangeError` is thrown. - -### TextDecoder.encoding - -Type: -* `String` - -> New in GJS 1.70 (GNOME 41) - -The `TextDecoder.encoding` read-only property returns a string containing the -name of the decoding algorithm used by the specific decoder. - -### TextDecoder.fatal - -Type: -* `Boolean` - -> New in GJS 1.70 (GNOME 41) - -The fatal property of the `TextDecoder` interface is a `Boolean` indicating -whether the error mode is fatal. If this value is `true`, the processed text -cannot be decoded because of malformed data. If this value is `false` malformed -data is replaced with placeholder characters. - -### TextDecoder.ignoreBOM - -Type: -* `Boolean` - -> New in GJS 1.70 (GNOME 41) - -The `ignoreBOM` property of the `TextDecoder` interface is a `Boolean` -indicating whether the byte order mark is ignored. - -### TextDecoder.decode(buffer, options) - -Parameters: -* buffer (`Number`) — Optional `ArrayBuffer`, a `TypedArray` or a `DataView` - object containing the text to decode. -* options (`Object`) — Optional dictionary with the `Boolean` property `fatal`, - indicating that additional data will follow in subsequent calls to `decode()`. - Set to `true` if processing the data in chunks, and `false` for the final - chunk or if the data is not chunked. It defaults to `false`. - -Returns: -* (`String`) — A string result - -> New in GJS 1.70 (GNOME 41) - -The `TextDecode.decode()` method returns a string containing the text, given in -parameters, decoded with the specific method for that `TextDecoder` object. - -### TextEncoder() - -Type: -* Static - -> New in GJS 1.70 (GNOME 41) - -The `TextEncoder()` constructor returns a newly created `TextEncoder` object -that will generate a byte stream with UTF-8 encoding. - -### TextEncoder.encoding - -Type: -* `String` - -> New in GJS 1.70 (GNOME 41) - -The `TextEncoder.encoding` read-only property returns a string containing the -name of the encoding algorithm used by the specific encoder. - -It can only have the following value `utf-8`. - -### TextEncoder.encode(string) - -Parameters: -* string (`String`) — A string containing the text to encode - -Returns: -* (`Uint8Array`) — A `Uint8Array` object containing UTF-8 encoded text - -> New in GJS 1.70 (GNOME 41) - -The `TextEncoder.encode()` method takes a string as input, and returns a -`Uint8Array` containing the text given in parameters encoded with the specific -method for that `TextEncoder` object. - -### TextEncoder.encodeInto(input, output) - -Parameters: -* input (`String`) — A string containing the text to encode -* output (`Uint8Array`) — A `Uint8Array` object instance to place the resulting - UTF-8 encoded text into. - -Returns: -* (`{String: Number}`) — An object containing the number of UTF-16 units read - and bytes written - -> New in GJS 1.70 (GNOME 41) - -The `TextEncoder.encode()` method takes a string as input, and returns a -`Uint8Array` containing the text given in parameters encoded with the specific -method for that `TextEncoder` object. - -The returned object contains two members: -* `read` - The number of UTF-16 units of code from the source that has been converted - over to UTF-8. This may be less than `string.length` if `uint8Array` did not - have enough space. -* `written` - The number of bytes modified in the destination `Uint8Array`. The bytes - written are guaranteed to form complete UTF-8 byte sequences. - diff -Nru gjs-1.74.0/doc/Environment.md gjs-1.72.2/doc/Environment.md --- gjs-1.74.0/doc/Environment.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Environment.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,8 +1,8 @@ -# Environment +## Environment GJS allows runtime configuration with a number of environment variables. -## General +### General * `GJS_PATH` @@ -17,7 +17,7 @@ Setting this variable to any value causes GJS to exit when an out-of-memory condition is encountered, instead of just printing a warning. -## JavaScript Engine +### JavaScript Engine * `JS_GC_ZEAL` @@ -31,7 +31,7 @@ JavaScript engine. -## Debugging +### Debugging * `GJS_DEBUG_HEAP_OUTPUT` @@ -75,7 +75,7 @@ Set this variable to print a timestamp when logging. -## Testing +### Testing * `GJS_COVERAGE_OUTPUT` diff -Nru gjs-1.74.0/doc/ESModules.md gjs-1.72.2/doc/ESModules.md --- gjs-1.74.0/doc/ESModules.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/ESModules.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,4 +1,4 @@ -# ECMAScript Modules +# Modules: ECMAScript modules > _This documentation is inspired by [Node.js' documentation](https://github.com/nodejs/node/blob/HEAD/doc/api/esm.md) > on ECMAScript modules._ @@ -223,7 +223,7 @@ ```js import GLib from 'gi://GLib'; const [filename] = GLib.filename_from_uri(import.meta.url); -const dirname = GLib.path_get_dirname(filename); +const dirname = GLib.path_get_dirname(path); ``` ## Interoperability with legacy `imports` modules diff -Nru gjs-1.74.0/doc/Format.md gjs-1.72.2/doc/Format.md --- gjs-1.74.0/doc/Format.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Format.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -# Format - -The `Format` module is a mostly deprecated module that implements `printf()` -style formatting for GJS. - -In most cases, native [template literals][template-literals] should be preferred -now, except in few situations like Gettext (See [Bug #60027][bug-60027]). - -```js -const foo = 'Pi'; -const bar = 1; -const baz = Math.PI; - -// expected result: "Pi to 2 decimal points: 3.14" - -// Native template literals -const str1 = `${foo} to ${bar*2} decimal points: ${baz.toFixed(bar*2)}` - -// Format.vprintf() -const str2 = Format.vprintf('%s to %d decimal points: %.2f', [foo, bar*2, baz]); -``` - -#### Import - -> Attention: This module is not available as an ECMAScript Module - -The `Format` module is available on the global `imports` object: - -```js -const Format = imports.format; -``` - -[template-literals]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals -[bug-60027]: https://savannah.gnu.org/bugs/?60027 - -### Format.format(...args) - -> Deprecated: Use [`Format.vprintf()`](#format-vprintf) instead - -Type: -* Prototype Function - -Parameters: -* args (`Any`) — Formatting substitutions - -Returns: -* (`String`) — A new formatted string - -This function was intended to extend the `String` object and provide a -`String.format` API for string formatting. - -Example usage: - -```js -const Format = imports.format; - -// Applying format() to the string prototype. -// -// This is highly discouraged, especially in GNOME Shell extensions where other -// extensions might overwrite it. Use Format.vprintf() directly instead. -String.prototype.format = Format.format; - -// Usage with String.prototype.format() -// expected result: "A formatted string" -const str = 'A %s %s'.format('formatted', 'string'); -``` - -### Format.printf(fmt, ...args) - -> Deprecated: Use [template literals][template-literals] with `print()` instead - -Type: -* Static - -Parameters: -* fmt (`String`) — A format template -* args (`Any`) — Formatting substitutions - -Substitute the specifiers in `fmt` with `args` and print the result to `stdout`. - -Example usage: - -```js -// expected output: A formatted string -Format.printf('A %s %s', 'formatted', 'string'); -``` - -### Format.vprintf(fmt, args) - -> Deprecated: Prefer [template literals][template-literals] when possible - -Type: -* Static - -Parameters: -* fmt (`String`) — A format template -* args (`Array(Any)`) — Formatting substitutions - -Returns: -* (`String`) — A new formatted string - -Substitute the specifiers in `fmt` with `args` and return a new string. It -supports the `%s`, `%d`, `%x` and `%f` specifiers. - -For `%f` it also supports precisions like `vprintf('%.2f', [1.526])`. All -specifiers can be prefixed with a minimum field width (e.g. -`vprintf('%5s', ['foo'])`). Unless the width is prefixed with `'0'`, the -formatted string will be padded with spaces. - -Example usage: - -```js -// expected result: "A formatted string" -const str = Format.vprintf('A %s %s', ['formatted', 'string']); - -// Usage with Gettext -Format.vprintf(_('%d:%d'), [11, 59]); -Format.vprintf( - Gettext.ngettext('I have %d apple', 'I have %d apples', num), [num]); -``` - -[template-literals]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals - diff -Nru gjs-1.74.0/doc/Gettext.md gjs-1.72.2/doc/Gettext.md --- gjs-1.74.0/doc/Gettext.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Gettext.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,233 +0,0 @@ -# Gettext - -> See also: [`examples/gettext.js`][examples-gettext] for usage examples - -This module provides a convenience layer for the "gettext" family of functions, -relying on GLib for the actual implementation. - -Example usage: - -```js -const Gettext = imports.gettext; - -Gettext.textdomain('myapp'); -Gettext.bindtextdomain('myapp', '/usr/share/locale'); - -let translated = Gettext.gettext('Hello world!'); -``` - -#### Import - -When using ESModules: - -```js -import Gettext from 'gettext'; -``` - -When using legacy imports: - -```js -const Gettext = imports.gettext; -``` - -[examples-gettext]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/examples/gettext.js - -### Gettext.LocaleCategory - -An enumeration of locale categories supported by GJS. - -* `CTYPE = 0` — Character classification -* `NUMERIC = 1` — Formatting of nonmonetary numeric values -* `TIME = 2` — Formatting of date and time values -* `COLLATE = 3` — String collation -* `MONETARY = 4` — Formatting of monetary values -* `MESSAGES = 5` — Localizable natural-language messages -* `ALL = 6` — All of the locale - -### Gettext.setlocale(category, locale) - -> Note: It is rarely, if ever, necessary to call this function in GJS - -Parameters: -* category (`Gettext.LocaleCategory`) — A locale category -* locale (`String`|`null`) — A locale string, or `null` to query the locale - -Returns: -* (`String`|`null`) — A locale string, or `null` if `locale` is not `null` - -Set or query the program's current locale. - -Example usage: - -```js -Gettext.setlocale(Gettext.LocaleCategory.MESSAGES, 'en_US.UTF-8'); -``` - -### Gettext.textdomain(domainName) - -Parameters: -* domainName (`String`) — A translation domain - -Set the default domain to `domainName`, which is used in all future gettext -calls. Note that this does not affect functions that take an explicit -`domainName` argument, such as `Gettext.dgettext()`. - -Typically this will be the project name or another unique identifier. For -example, GNOME Calculator might use something like `"gnome-calculator"` while a -GNOME Shell Extension might use its extension UUID. - -### Gettext.bindtextdomain(domainName, dirName) - -Parameters: -* domainName (`String`) — A translation domain -* dirName (`String`) — A directory path - -Specify `dirName` as the directory that contains translations for `domainName`. - -In most cases, `dirName` will be the system locale directory, such as -`/usr/share/locale`. GNOME Shell's `ExtensionUtils.initTranslations()` method, -on the other hand, will check an extension's directory for a `locale` -subdirectory before falling back to the system locale directory. - -### Gettext.gettext(msgid) - -> Note: This is equivalent to calling `Gettext.dgettext(null, msgid)` - -Parameters: -* msgid (`String`) — A string to translate - -Returns: -* (`String`) — A translated message - -This function is a wrapper of `dgettext()` which does not translate the message -if the default domain as set with `Gettext.textdomain()` has no translations for -the current locale. - -### Gettext.dgettext(domainName, msgid) - -> Note: This is an alias for [`GLib.dgettext()`][gdgettext] - -Parameters: -* domainName (`String`|`null`) — A translation domain -* msgid (`String`) — A string to translate - -Returns: -* (`String`) — A translated message - -This function is a wrapper of `dgettext()` which does not translate the message -if the default domain as set with `Gettext.textdomain()` has no translations for -the current locale. - -[gdgettext]: https://gjs-docs.gnome.org/glib20/glib.dgettext - -### Gettext.dcgettext(domainName, msgid, category) - -> Note: This is an alias for [`GLib.dcgettext()`][gdcgettext] - -Parameters: -* domainName (`String`|`null`) — A translation domain -* msgid (`String`) — A string to translate -* category (`Gettext.LocaleCategory`) — A locale category - -Returns: -* (`String`) — A translated message - -This is a variant of `Gettext.dgettext()` that allows specifying a locale -category. - -[gdcgettext]: https://gjs-docs.gnome.org/glib20/glib.dcgettext - -### Gettext.ngettext(msgid1, msgid2, n) - -> Note: This is equivalent to calling -> `Gettext.dngettext(null, msgid1, msgid2, n)` - -Parameters: -* msgid1 (`String`) — The singular form of the string to be translated -* msgid2 (`String`) — The plural form of the string to be translated -* n (`Number`) — The number determining the translation form to use - -Returns: -* (`String`) — A translated message - -Translate a string that may or may not be plural, like "I have 1 apple" and -"I have 2 apples". - -In GJS, this should be used in conjunction with [`Format.vprintf()`][vprintf], -which supports the same substitutions as `printf()`: - -```js -const numberOfApples = Math.round(Math.random() + 1); -const translated = Format.vprintf(Gettext.ngettext('I have %d apple', - 'I have %d apples', numberOfApples), [numberOfApples]); -``` - -[vprintf]: https://gjs-docs.gnome.org/gjs/format.md#format-vprintf - -### Gettext.dngettext(domainName, msgid1, msgid2, n) - -> Note: This is an alias for [`GLib.dngettext()`][gdngettext] - -Parameters: -* domainName (`String`|`null`) — A translation domain -* msgid1 (`String`) — A string to translate -* msgid2 (`String`) — A pluralized string to translate -* n (`Number`) — The number determining the translation form to use - -Returns: -* (`String`) — A translated message - -This function is a wrapper of `dngettext()` which does not translate the message -if the default domain as set with `textdomain()` has no translations for the -current locale. - -[gdngettext]: https://gjs-docs.gnome.org/glib20/glib.dngettext - -### Gettext.pgettext(context, msgid) - -> Note: This is equivalent to calling `Gettext.dpgettext(null, context, msgid)` - -Parameters: -* context (`String`|`null`) — A context to disambiguate `msgid` -* msgid (`String`) — A string to translate - -Returns: -* (`String`) — A translated message - -This is a variant of `Gettext.dgettext()` which supports a disambiguating -message context. - -This is used to disambiguate a translation where the same word may be used -differently, depending on the situation. For example, in English "read" is the -same for both past and present tense, but may not be in other languages. - -### Gettext.dpgettext(domainName, context, msgid) - -> Note: This is an alias for [`GLib.dpgettext2()`][gdpgettext2] - -Parameters: -* domainName (`String`|`null`) — A translation domain -* context (`String`|`null`) — A context to disambiguate `msgid` -* msgid (`String`) — A string to translate - -Returns: -* (`String`) — A translated message - -This is a variant of `Gettext.dgettext()` which supports a disambiguating -message context. - -[gdpgettext2]: https://gjs-docs.gnome.org/glib20/glib.dpgettext2 - -### Gettext.domain(domainName) - -> Note: This method is specific to GJS - -Parameters: -* domainName (`String`) — A domain name - -Returns: -* (`Object`) — An object with common gettext methods - -Create an object with bindings for `Gettext.gettext()`, `Gettext.ngettext()`, -and `Gettext.pgettext()`, bound to a `domainName`. - diff -Nru gjs-1.74.0/doc/Hacking.md gjs-1.72.2/doc/Hacking.md --- gjs-1.74.0/doc/Hacking.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Hacking.md 2022-08-08 05:05:12.000000000 +0000 @@ -37,7 +37,7 @@ ## Dependencies GJS requires five other libraries to be installed: GLib, libffi, -gobject-introspection, SpiderMonkey (also called "mozjs102" on some +gobject-introspection, SpiderMonkey (also called "mozjs91" on some systems.) and the build tool Meson. The readline library is not required, but strongly recommended. We recommend installing your system's development packages for GLib, @@ -70,15 +70,15 @@ need to build it yourself. Install SpiderMonkey using your system's package manager instead: - +
Fedora - sudo dnf install mozjs102-devel + sudo dnf install mozjs91-devel
If you _are_ writing C++ code, then please build SpiderMonkey yourself @@ -86,7 +86,7 @@ This can save you time later when you submit your merge request, because the code will be checked using the debugging features. -To build SpiderMonkey, follow the instructions on [this page](https://github.com/mozilla-spidermonkey/spidermonkey-embedding-examples/blob/esr102/docs/Building%20SpiderMonkey.md) to download the source code and build the library. +To build SpiderMonkey, follow the instructions on [this page](https://github.com/mozilla-spidermonkey/spidermonkey-embedding-examples/blob/esr91/docs/Building%20SpiderMonkey.md) to download the source code and build the library. If you are using `-Dprefix` to build GJS into a different path, then make sure to use the same build prefix for SpiderMonkey with `--prefix`. @@ -152,7 +152,7 @@ To see which GC zeal options are available: ```sh -JS_GC_ZEAL=-1 js102 +JS_GC_ZEAL=-1 js91 ``` We include three test setups, `extra_gc`, `pre_verify`, and @@ -216,7 +216,7 @@ instrumentation enabled, run the test suite to collect the coverage data, and open the generated HTML report. -[embedder](https://github.com/spidermonkey-embedders/spidermonkey-embedding-examples/blob/esr102/docs/Building%20SpiderMonkey.md) +[embedder](https://github.com/spidermonkey-embedders/spidermonkey-embedding-examples/blob/esr91/docs/Building%20SpiderMonkey.md) ## Troubleshooting diff -Nru gjs-1.74.0/doc/Home.md gjs-1.72.2/doc/Home.md --- gjs-1.74.0/doc/Home.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Home.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,4 +1,69 @@ # GJS: Javascript Bindings for GNOME -This page has moved to [`README.md`](README.md). +The current stable series is built on Mozilla's SpiderMonkey 91, +featuring **ECMAScript 2022** and GObject Introspection making most of +the **GNOME platform API** available. +To find out when a language feature was implemented in GJS, review [NEWS][gjs-news] in the GitLab repository. In many cases older versions of GJS can be supported using [polyfills][mdn-polyfills] and [legacy-style GJS classes](Modules.md#lang). + +GJS includes some built-in modules like Cairo and Gettext, as well as helpers for some core APIs like DBus and GVariants. See the [Modules](Modules.md) page for an overview of the built-in modules and their usage. + +[gjs-news]: https://gitlab.gnome.org/GNOME/gjs/raw/HEAD/NEWS +[mdn-polyfills]: https://developer.mozilla.org/docs/Glossary/Polyfill + +## GNOME API Documentation + +There is official [GNOME API Documentation][gjs-docs] for GJS, including +everything from GLib and Gtk to Soup and WebKit2. + +The [Mapping](Mapping.md) page has an overview of GNOME API usage in GJS such as subclassing, constants and flags, functions with multiple return values, and more. + +There are also a growing number of [examples][gjs-examples] and thorough tests of language features in the [test suite][gjs-tests]. + +[gjs-docs]: https://gjs-docs.gnome.org/ +[gjs-examples]: https://gitlab.gnome.org/GNOME/gjs/tree/HEAD/examples +[gjs-tests]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/installed-tests/js + +## Standalone Applications + +It's possible to write standalone applications with GJS for the GNOME Desktop, and infrastructure for Gettext, GSettings and GResources via the `package` import. There is a package specification, template repository available and plans for an in depth tutorial. + +* [GJS Package Specification](https://gitlab.gnome.org/GNOME/gjs/-/blob/HEAD/doc/Package/Specification.md) +* [GJS Package Template](https://github.com/gcampax/gtk-js-app) + +GNOME Applications written in GJS: + +* [GNOME Characters](https://gitlab.gnome.org/GNOME/gnome-characters) +* [GNOME Documents](https://gitlab.gnome.org/GNOME/gnome-documents) +* [GNOME Maps](https://gitlab.gnome.org/GNOME/gnome-maps) +* [GNOME Sound Recorder](https://gitlab.gnome.org/GNOME/gnome-sound-recorder) +* [GNOME Weather](https://gitlab.gnome.org/GNOME/gnome-weather) +* [GNOME Books](https://gitlab.gnome.org/GNOME/gnome-books) +* [Polari](https://gitlab.gnome.org/GNOME/polari) IRC Client + +Third party applications written in GJS: + +* [Tangram](https://github.com/sonnyp/Tangram) +* [Quick Lookup](https://github.com/johnfactotum/quick-lookup) +* [Foliate](https://github.com/johnfactotum/foliate) +* [Marker](https://github.com/fabiocolacio/Marker) +* [Gnomit](https://github.com/small-tech/gnomit) +* [Clapper](https://github.com/Rafostar/clapper/) +* [Flatseal](https://github.com/tchx84/Flatseal) +* [Almond](https://github.com/stanford-oval/almond-gnome/) +* [Commit](https://github.com/sonnyp/commit/) +* [Junction](https://github.com/sonnyp/Junction) +* [Oh My SVG](https://github.com/sonnyp/OhMySVG) + +## Getting Help + +* Discourse: https://discourse.gnome.org/ +* Chat: https://matrix.to/#/#javascript:gnome.org +* Issue/Bug Tracker: https://gitlab.gnome.org/GNOME/gjs/issues +* StackOverflow: https://stackoverflow.com/questions/tagged/gjs + +## External Links + +* [GObjectIntrospection](https://wiki.gnome.org/action/show/Projects/GObjectIntrospection) +* [GNOME Developer Platform Demo](https://developer-old.gnome.org/gnome-devel-demos/stable/js.html) (Some older examples that still might be informative) +* [GNOME Shell Extensions](https://gjs.guide/extensions) diff -Nru gjs-1.74.0/doc/Lang.md gjs-1.72.2/doc/Lang.md --- gjs-1.74.0/doc/Lang.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Lang.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,141 +0,0 @@ -# Lang - -The `Lang` module is a collection of deprecated features that have been -completely superseded by standard ECMAScript. It remains a part of GJS for -backwards-compatibility reasons, but should never be used in new code. - -#### Import - -> Attention: This module is not available as an ECMAScript Module - -The `Lang` module is available on the global `imports` object: - -```js -const Lang = imports.lang -``` - -### Lang.bind(thisArg, function, ...args) - -> Deprecated: Use [`Function.prototype.bind()`][function-bind] instead - -Type: -* Static - -Parameters: -* thisArg (`Object`) — A JavaScript object -* callback (`Function`) — A function reference -* args (`Any`) — A function reference - -Returns: -* (`Function`) — A new `Function` instance, bound to `thisArg` - -Binds a function to a scope. - -[function-bind]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind - -### Lang.Class(object) - -> Deprecated: Use native [JavaScript Classes][js-class] instead - -Type: -* Static - -Parameters: -* object (`Object`) — A JavaScript object - -Returns: -* (`Object`) — A JavaScript class expression - -... - -Example usage: - -```js -const MyLegacyClass = new Lang.Class({ - _init: function() { - let fnorb = new FnorbLib.Fnorb(); - fnorb.connect('frobate', Lang.bind(this, this._onFnorbFrobate)); - }, - - _onFnorbFrobate: function(fnorb) { - this._updateFnorb(); - } -}); -``` - -[js-class]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Classes - -### Lang.copyProperties(source, dest) - -> Deprecated: Use [`Object.assign()`][object-assign] instead - -Type: -* Static - -Parameters: -* source (`Object`) — The source object -* dest (`Object`) — The target object - -Copy all properties from `source` to `dest`, including those that are prefixed -with an underscore (e.g. `_privateFunc()`). - -[object-assign]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign - -### Lang.copyPublicProperties(source, dest) - -> Deprecated: Use [`Object.assign()`][object-assign] instead - -Type: -* Static - -Parameters: -* source (`Object`) — The source object -* dest (`Object`) — The target object - -Copy all public properties from `source` to `dest`, excluding those that are -prefixed with an underscore (e.g. `_privateFunc()`). - -[object-assign]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign - -### Lang.countProperties(object) - -> Deprecated: Use [`Object.assign()`][object-assign] instead - -Type: -* Static - -Parameters: -* object (`Object`) — A JavaScript object - -[object-assign]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign - -### Lang.getMetaClass(object) - -Type: -* Static - -Parameters: -* object (`Object`) — A JavaScript object - -Returns: -* (`Object`|`null`) — A `Lang.Class` meta object - -... - -### Lang.Interface(object) - -> Deprecated: Use native [JavaScript Classes][js-class] instead - -Type: -* Static - -Parameters: -* object (`Object`) — A JavaScript object - -Returns: -* (`Object`) — A JavaScript class expression - -... - -[js-class]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Classes - diff -Nru gjs-1.74.0/doc/Logging.md gjs-1.72.2/doc/Logging.md --- gjs-1.74.0/doc/Logging.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Logging.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,121 +1,115 @@ -# Logging - GJS includes a number of built-in functions for logging and aiding debugging, in addition to those available as a part of the GNOME APIs. -In most cases, the [`console`][console] suite of functions should be preferred -for logging in GJS. - -#### Import - -The functions in this module are available globally, without import. - -[console]: https://gjs-docs.gnome.org/gjs/console.md - -### log(message) - -> See also: [`console.log()`][console-log] +# Built-in Functions -Type: -* Static +GJS includes four built-in logging functions: `log()`, `logError()`, `print()` +and `printerr()`. These functions are available globally (ie. without import) +and the source for these is found in [global.cpp][global-cpp]. -Parameters: -* message (`Any`) — A string or any coercible value +### log() -Logs a message with severity equal to -[`GLib.LogLevelFlags.LEVEL_MESSAGE`][gloglevelflagsmessage]. +`log()` is the most basic function available, taking a single argument as a +`String` or other object which can be coerced to a `String`. The string, or +object coerced to a string, is logged with `g_message()` from GLib. ```js // expected output: JS LOG: Some message log('Some message'); // expected output: JS LOG: [object Object] -log({key: 'value'}); +log(new Object()); ``` -[console-log]: https://gjs-docs.gnome.org/gjs/console.md#console-log -[gloglevelflagsmessage]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_message - -### logError(error, prefix) - -> See also: [`console.trace()`][console-trace] - -Type: -* Static - -Parameters: -* error (`Error`) — An `Error` or [`GLib.Error`][gerror] object -* prefix (`String`) — Optional prefix for the message - -Logs a stack trace for `error`, with an optional prefix, with severity equal to -[`GLib.LogLevelFlags.LEVEL_WARNING`][gloglevelflagswarning]. +### logError() -This function is commonly used in conjunction with `try...catch` blocks to log -errors while still trapping the exception: +`logError()` is a more useful function for debugging that logs the stack trace of +a JavaScript `Error()` object, with an optional prefix. -```js -try { - throw new Error('Some error occured'); -} catch (e) { - logError(e, 'FooError'); -} -``` - -It can also be passed directly to the `catch()` clause of a `Promise` chain: +It is commonly used in conjunction with `try...catch` blocks to log errors while +still trapping the exception. An example in `gjs-console` with a backtrace: ```js -Promise.reject().catch(logError); +$ gjs +gjs> try { +.... throw new Error('Some error occured'); +.... } catch (e) { +.... logError(e, 'FooError'); +.... } + +(gjs:28115): Gjs-WARNING **: 19:28:13.334: JS ERROR: FooError: Error: Some error occurred +@typein:2:16 +@:1:34 ``` -[console-trace]: https://gjs-docs.gnome.org/gjs/console.md#console-trace -[gerror]: https://gjs-docs.gnome.org/glib20/glib.error -[gloglevelflagswarning]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags#default-level_warning - -### print(...messages) - -> Note: this function is not useful for GNOME Shell extensions -Type: -* Static +### print() & printerr() -Parameters: -* messages (`Any`) — Any number of strings or coercible values - -Takes any number of strings (or values that can be coerced to strings), joins -them with a space and appends a newline character (`\n`). - -The resulting string is printed directly to `stdout` of the current process with -[`g_print()`][gprint]. +`print()` takes any number of string (or coercible) arguments, joins them with a +space and appends a newline (`\n`). The resulting message will be printed +directly to `stdout` of the current process using `g_print()`. + +`printerr()` is exactly like `print()`, except the resulting message is printed +to `stderr` with `g_printerr()`. + +These functions are generally less useful for debugging code in programs that +embed GJS like GNOME Shell, where it is less convenient to access the `stdout` +and `stderr` pipes. ```js -$ gjs -c "print('foobar', 42, {});" -foobar 42 [object Object] -$ +$ gjs +gjs> print('some', 'string', 42); +some string 42$ +gjs> printerr('some text 42'); +some text ``` -[gprint]: https://docs.gtk.org/glib/func.print.html -### printerr(...messages) +# GLib Functions -> Note: this function is not useful for GNOME Shell extensions +Aside from the built-in functions in GJS, many functions from GLib can be used +to log messages at different severity levels and assist in debugging. -Type: -* Static +Below is a common pattern for defining a series of logging functions as used in +[Polari][polari] and some other GJS applications: -Parameters: -* messages (`Any`) — Any number of strings or coercible values +```js +const GLib = imports.gi.GLib; -Takes any number of strings (or values that can be coerced to strings), joins -them with a space and appends a newline character (`\n`). +var LOG_DOMAIN = 'Polari'; -The resulting string is printed directly to `stderr` of the current process with -[`g_printerr()`][gprinterr]. +function _makeLogFunction(level) { + return message => { + let stack = (new Error()).stack; + let caller = stack.split('\n')[1]; + + // Map from resource- to source location + caller = caller.replace('resource:///org/gnome/Polari/js', 'src'); + + let [code, line] = caller.split(':'); + let [func, file] = code.split(/\W*@/); + GLib.log_structured(LOG_DOMAIN, level, { + 'MESSAGE': `${message}`, + 'SYSLOG_IDENTIFIER': 'org.gnome.Polari', + 'CODE_FILE': file, + 'CODE_FUNC': func, + 'CODE_LINE': line + }); + }; +} -```js -$ gjs -c "printerr('foobar', 42, {});" -foobar 42 [object Object] -$ +globalThis.log = _makeLogFunction(GLib.LogLevelFlags.LEVEL_MESSAGE); +globalThis.debug = _makeLogFunction(GLib.LogLevelFlags.LEVEL_DEBUG); +globalThis.info = _makeLogFunction(GLib.LogLevelFlags.LEVEL_INFO); +globalThis.warning = _makeLogFunction(GLib.LogLevelFlags.LEVEL_WARNING); +globalThis.critical = _makeLogFunction(GLib.LogLevelFlags.LEVEL_CRITICAL); +globalThis.error = _makeLogFunction(GLib.LogLevelFlags.LEVEL_ERROR); + +// Log all messages when connected to the journal +if (GLib.log_writer_is_journald(2)) + GLib.setenv('G_MESSAGES_DEBUG', LOG_DOMAIN, false); ``` -[gprinterr]: https://docs.gtk.org/glib/func.printerr.html +[global-cpp]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/gjs/global.cpp +[polari]: https://gitlab.gnome.org/GNOME/polari/blob/HEAD/src/main.js diff -Nru gjs-1.74.0/doc/Mainloop.md gjs-1.72.2/doc/Mainloop.md --- gjs-1.74.0/doc/Mainloop.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Mainloop.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,213 +0,0 @@ -# Mainloop - -The `Mainloop` module is a convenience layer for some common event loop methods -in GLib, such as [`GLib.timeout_add()`][gtimeoutadd]. - -This module is not generally recommended, but is documented for the sake of -existing code. Each method below contains links to the corresponding GLib -method for reference. - -For an introduction to the GLib event loop, see the -[Asynchronous Programming Tutorial][async-tutorial]. - -[async-tutorial]: https://gjs.guide/guides/gjs/asynchronous-programming.html -[gtimeoutadd]: https://gjs-docs.gnome.org/glib20/glib.timeout_add - -#### Import - -> Attention: This module is not available as an ECMAScript Module - -The `Mainloop` module is available on the global `imports` object: - -```js -const Mainloop = imports.mainloop -``` - -### Mainloop.idle_add(handler, priority) - -> See also: [`GLib.idle_add()`][gidleadd] - -Type: -* Static - -Parameters: -* handler (`Function`) — The function to call -* priority (`Number`) — Optional priority - -Returns: -* (`GLib.Source`) — The newly-created idle source - -Adds a function to be called whenever there are no higher priority events -pending. If the function returns `false` it is automatically removed from the -list of event sources and will not be called again. - -If not given, `priority` defaults to `GLib.PRIORITY_DEFAULT_IDLE`. - -[gidleadd]: https://gjs-docs.gnome.org/glib20/glib.idle_add - -### Mainloop.idle_source(handler, priority) - -> See also: [`GLib.idle_source_new()`][gidlesourcenew] - -Type: -* Static - -Parameters: -* handler (`Function`) — The function to call -* priority (`Number`) — Optional priority - -Returns: -* (`GLib.Source`) — The newly-created idle source - -Creates a new idle source. - -If not given, `priority` defaults to `GLib.PRIORITY_DEFAULT_IDLE`. - -[gidlesourcenew]: https://gjs-docs.gnome.org/glib20/glib.idle_source_new - -### Mainloop.quit(name) - -> See also: [`GLib.MainLoop.quit()`][gmainloopquit] - -Type: -* Static - -Parameters: -* name (`String`) — Optional name - -Stops a main loop from running. Any calls to `Mainloop.run(name)` for the loop -will return. - -If `name` is given, this function will create a new [`GLib.MainLoop`][gmainloop] -if necessary. - -[gmainloop]: https://gjs-docs.gnome.org/glib20/glib.mainloop -[gmainloopquit]: https://gjs-docs.gnome.org/glib20/glib.mainloop#method-quit - -### Mainloop.run(name) - -> See also: [`GLib.MainLoop.run()`][gmainlooprun] - -Type: -* Static - -Parameters: -* name (`String`) — Optional name - -Runs a main loop until `Mainloop.quit()` is called on the loop. - -If `name` is given, this function will create a new [`GLib.MainLoop`][gmainloop] -if necessary. - -[gmainloop]: https://gjs-docs.gnome.org/glib20/glib.mainloop -[gmainlooprun]: https://gjs-docs.gnome.org/glib20/glib.mainloop#method-run - -### Mainloop.source_remove(id) - -> See also: [`GLib.Source.remove()`][gsourceremove] - -Type: -* Static - -Parameters: -* id (`Number`) — The ID of the source to remove - -Returns: -* (`Boolean`) — For historical reasons, this function always returns `true` - -Removes the source with the given ID from the default main context. - -[gsourceremove]: https://gjs-docs.gnome.org/glib20/glib.source#function-remove - -### Mainloop.timeout_add(timeout, handler, priority) - -> See also: [`GLib.timeout_add()`][gtimeoutadd] - -Type: -* Static - -Parameters: -* timeout (`Number`) — The timeout interval in milliseconds -* handler (`Function`) — The function to call -* priority (`Number`) — Optional priority - -Returns: -* (`GLib.Source`) — The newly-created timeout source - -Sets a function to be called at regular intervals, with the given priority. The -function is called repeatedly until it returns `false`, at which point the -timeout is automatically destroyed and the function will not be called again. - -The scheduling granularity/accuracy of this source will be in milliseconds. If -not given, `priority` defaults to `GLib.PRIORITY_DEFAULT`. - -[gtimeoutadd]: https://gjs-docs.gnome.org/glib20/glib.timeout_add - -### Mainloop.timeout_add_seconds(timeout, handler, priority) - -> See also: [`GLib.timeout_add_seconds()`][gtimeoutaddseconds] - -Type: -* Static - -Parameters: -* timeout (`Number`) — The timeout interval in seconds -* handler (`Function`) — The function to call -* priority (`Number`) — Optional priority - -Returns: -* (`GLib.Source`) — The newly-created timeout source - -Sets a function to be called at regular intervals, with the given priority. The -function is called repeatedly until it returns `false`, at which point the -timeout is automatically destroyed and the function will not be called again. - -The scheduling granularity/accuracy of this source will be in seconds. If not -given, `priority` defaults to `GLib.PRIORITY_DEFAULT`. - -[gtimeoutaddseconds]: https://gjs-docs.gnome.org/glib20/glib.timeout_add_seconds - -### Mainloop.timeout_source(timeout, handler, priority) - -> See also: [`GLib.timeout_source_new()`][gtimeoutsourcenew] - -Type: -* Static - -Parameters: -* timeout (`Number`) — The timeout interval in milliseconds -* handler (`Function`) — The function to call -* priority (`Number`) — Optional priority - -Returns: -* (`GLib.Source`) — The newly-created timeout source - -Creates a new timeout source. - -The scheduling granularity/accuracy of this source will be in milliseconds. If -not given, `priority` defaults to `GLib.PRIORITY_DEFAULT`. - -[gtimeoutadd]: https://gjs-docs.gnome.org/glib20/glib.timeout_source_new - -### Mainloop.timeout_seconds_source(timeout, handler, priority) - -> See also: [`GLib.timeout_source_new_seconds()`][gtimeoutsourcenewseconds] - -Type: -* Static - -Parameters: -* timeout (`Number`) — The timeout interval in seconds -* handler (`Function`) — The function to call -* priority (`Number`) — Optional priority - -Returns: -* (`GLib.Source`) — The newly-created timeout source - -Creates a new timeout source. - -The scheduling granularity/accuracy of this source will be in seconds. If not -given, `priority` defaults to `GLib.PRIORITY_DEFAULT`. - -[gtimeoutsourcenewseconds]: https://gjs-docs.gnome.org/glib20/glib.timeout_source_new_seconds - diff -Nru gjs-1.74.0/doc/Mapping.md gjs-1.72.2/doc/Mapping.md --- gjs-1.74.0/doc/Mapping.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Mapping.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,48 +1,32 @@ -# GObject Usage in GJS +## GObject Construction, Subclassing, Templates and GType -This is general overview of how to use GObject in GJS. Whenever possible GJS -tries to use idiomatic JavaScript, so this document may be of more interest to -C or Python developers that are new to GJS. +### Constructing GObjects -## GObject Construction +GObjects can be constructed with the `new` operator, just like JavaScript objects, and usually take an Object map of properties. -GObjects can be constructed with the `new` operator, and usually take an `Object` map of properties: +The object that you pass to `new` (e.g. `Gtk.Label` in `let label = new Gtk.Label()`) is the **constructor object**, that contains constructor methods and static methods such as `Gio.File.new_for_path()`. +It's different from the **prototype object** containing instance methods. +For more information on JavaScript's prototypal inheritance, this [blog post][understanding-javascript-prototypes] is a good resource. ```js -const label = new Gtk.Label({ +let label = new Gtk.Label({ label: 'gnome.org', halign: Gtk.Align.CENTER, hexpand: true, use_markup: true, - visible: true, + visible: true }); -``` - -The object that you pass to `new` (`Gtk.Label` in the example above) is the -**constructor object**, which may also contain static methods and constructor -methods such as `Gio.File.new_for_path()`: -```js -const file = Gio.File.new_for_path('/proc/cpuinfo'); +let file = Gio.File.new_for_path('/proc/cpuinfo'); ``` -The **constructor object** is different from the **prototype object** -containing instance methods. For more information on JavaScript's prototypal -inheritance, this [blog post][understanding-javascript-prototypes] is a good -resource. - [understanding-javascript-prototypes]: https://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/ -## GObject Subclassing - -> See also: [`GObject.registerClass()`](overrides.md#gobject-registerclass) +### Subclassing GObjects -GObjects have facilities for defining properties, signals and implemented -interfaces. Additionally, Gtk objects support defining a CSS name and composite -template. +GObjects have facilities for defining properties, signals and implemented interfaces. Additionally, Gtk objects support defining a CSS name and composite template. -The **constructor object** is also passed to the `extends` keyword in class -declarations when subclassing GObjects. +The **constructor object** is also passed to the `extends` keyword in class declarations when subclassing GObjects. ```js var MyLabel = GObject.registerClass({ @@ -64,41 +48,63 @@ }); ``` -Note that before GJS 1.72 (GNOME 42), you had to override `_init()` and -chain-up with `super._init()`. This behaviour is still supported for -backwards-compatibility, but new code should use the standard `constructor()` -and chain-up with `super()`. +Note that before GJS 1.72 (GNOME 42), you had to override `_init()` instead of `constructor()` and chain-up with `super._init()`. This is still supported in GJS 1.72 and later. -For a more complete introduction to GObject subclassing in GJS, see the -[GObject Tutorial][gobject-subclassing]. +### GType Objects -[gobject-subclassing]: https://gjs.guide/guides/gobject/subclassing.html#subclassing-gobject +This is the object that represents a type in the GObject type system. Internally a GType is an integer, but you can't access that integer in GJS. -## GObject Properties +The `$gtype` property gives the GType object for the given type. This is the proper way to find the GType given an object or a class. For a class, `GObject.type_from_name('GtkLabel')` would work too if you know the GType name, but only if you had previously constructed a Gtk.Label object. -GObject properties may be retrieved and set using native property style access -or GObject get/set methods. Note that variables in JavaScript can't contain -hyphens (-) so when a property name is *unquoted* use an underscore (_). +```js +log(Gtk.Label.$gtype); +log(labelInstance.constructor.$gtype); +// expected output: [object GType for 'GtkLabel'] +``` + +The `name` property of GType objects gives the GType name as a string ('GtkLabel'). This is the proper way to find the type name given an object or a class. + +User defined subclasses' GType name will be the class name prefixed with `Gjs_`by default. +If you want to specify your own name, you can pass it as the value for the `GTypeName` property to `GObject.registerClass()`. +This will be relevant in situations such as defining a composite template for a GtkWidget subclass. ```js -let value; +log(Gtk.Label.$gtype.name); +log(labelInstance.constructor.$gtype.name); +// expected output: GtkLabel -value = label.use_markup; -value = label.get_use_markup(); -value = label['use-markup']; +log(MyLabel.$gtype.name); +// expected output: Gjs_MyLabel +``` -label.use_markup = value; -label.set_use_markup(value); -label['use-markup'] = value; +[`instanceof`][mdn-instanceof] can be used to compare an object instance to a **constructor object**. -label.connect('notify::use-markup', () => {}); +```js +log(typeof labelInstance); +// expected output: object + +log(labelInstance instanceof Gtk.Label); +// expected output: true ``` -GObject subclasses can register properties, which is necessary if you want to -use `GObject.notify()` or `GObject.bind_property()`. +[mdn-instanceof]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/instanceof -> Warning: Never use underscores in property names in the ParamSpec, because of -> the conversion between underscores and hyphens mentioned above. +## Properties + +GObject properties may be retrieved and set using native property style access or GObject get/set methods. Note that variables in JavaScript can't contain hyphens (-) so when a property name is *unquoted* use an underscore (_). + +```js +if (!label.use_markup) { + label.connect('notify::use-markup', () => { ... }); + label.use_markup = true; + label['use-markup'] = true; + label.set_use_markup(true); +} +``` + +GObject subclasses can register properties, which is necessary if you want to use `GObject.notify()` or `GObject.bind_property()`. + +**NOTE:** Never use underscores in property names in the ParamSpec, because of the conversion between underscores and hyphens mentioned above. ```js var MyLabel = GObject.registerClass({ @@ -127,37 +133,28 @@ }); ``` -If you just want a simple property that you can get change notifications from, -you can leave out the getter and setter and GJS will attempt to do the right -thing. However, if you define one, you have to define both (unless the property -is read-only or write-only). - -The 'default value' parameter passed to `GObject.ParamSpec` will be taken into -account if you omit the getter and setter. If you write your own getter and -setter, you have to implement the default value yourself, as in the above -example. +If you just want a simple property that you can get change notifications from, you can leave out the getter and setter and GJS will attempt to do the right thing. +However, if you define one, you have to define both (unless the property is read-only or write-only). -## GObject Signals +The 'default value' parameter passed to `GObject.ParamSpec` will be taken into account if you omit the getter and setter. +If you write your own getter and setter, you have to implement the default value yourself, as in the above example. -> See also: The [`Signals`][signals-module] module contains an GObject-like -> signal framework for native Javascript classes +## Signals -Every object inherited from GObject has `connect()`, `connect_after()`, -`disconnect()` and `emit()` methods. +Every object inherited from GObject has `connect()`, `connect_after()`, `disconnect()` and `emit()` methods. ```js -// Connecting a signal handler let handlerId = label.connect('activate-link', (label, uri) => { - Gtk.show_uri_on_window(label.get_toplevel(), uri, - Gdk.get_current_time()); - + Gtk.show_uri_on_window( + label.get_toplevel(), + uri, + Gdk.get_current_time() + ); return true; }); -// Emitting a signal label.emit('activate-link', 'https://www.gnome.org'); -// Disconnecting a signal handler label.disconnect(handlerId); ``` @@ -179,90 +176,31 @@ }); ``` -[signals-module]: https://gjs-docs.gnome.org/gjs/signals.md - -## GType Objects - -> See also: [`GObject.Object.$gtype`][gobject-gtype] and -> [`GObject.registerClass()`][gobject-registerclass] - -This is the object that represents a type in the GObject type system. Internally -a GType is an integer, but you can't access that integer in GJS. - -The GType object is simple wrapper with two members: - -* name (`String`) — A read-only string property, such as `"GObject"` -* toString() (`Function`) — Returns a string representation of the GType, such - as `"[object GType for 'GObject']"` - -Generally this object is not useful and better alternatives exist. Whenever a -GType is expected as an argument, you can simply pass a **constructor object**: - -```js -// Passing a "constructor object" in place of a GType -const listInstance = Gio.ListStore.new(Gtk.Widget); - -// This also works for GObject.Interface types, such as Gio.ListModel -const pspec = Gio.ParamSpec.object('list', '', '', GObject.ParamFlags.READABLE, - Gio.ListModel); -``` - -To confirm the GType of an object instance, you can just use the standard -[`instanceof` operator][mdn-instanceof]: - -```js -// Comparing an instance to a "constructor object" -const objectInstance = new GObject.Object(); - -// Comparing an instance to a "constructor object" -if (objectInstance instanceof GObject.Object) - log(true); - -// GtkLabel inherits from GObject.Object, so both of these are true -const labelInstance = new Gtk.Label(); - -if (labelInstance instance of GObject.Object) - log(true); - -if (labelInstance instance of Gtk.Label) - log(true); -``` - -[gobject-gtype]: https://gjs-docs.gnome.org/gjs/overrides.md#gobject-gtype -[gobject-registerclass]: https://gjs-docs.gnome.org/gjs/overrides.md#gobject-registerclass -[mdn-instanceof]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/instanceof +**NOTE:** GJS also includes a built-in [`signals`](Modules#signals) module for applying signals to native JavaScript classes. ## Enumerations and Flags -Both enumerations and flags appear as entries under the namespace, with -associated member properties. These are available in the official GJS -[GNOME API documentation][gjs-docs]. - -Examples: +Both enumerations and flags appear as entries under the namespace, with associated member properties. These are available in the official GJS [GNOME API documentation][gjs-docs]. ```js // enum GtkAlign, member GTK_ALIGN_CENTER Gtk.Align.CENTER; - // enum GtkWindowType, member GTK_WINDOW_TOPLEVEL Gtk.WindowType.TOPLEVEL; - // enum GApplicationFlags, member G_APPLICATION_FLAGS_NONE Gio.ApplicationFlags.FLAGS_NONE ``` -Flags can be manipulated using native [bitwise operators][mdn-bitwise]: +Flags can be manipulated using native [bitwise operators][mdn-bitwise]. ```js -// Setting a flags property with a combination of flags -const myApp = new Gio.Application({ - flags: Gio.ApplicationFlags.HANDLES_OPEN | - Gio.ApplicationFlags.HANDLES_COMMAND_LINE +let myApp = new Gio.Application({ + flags: Gio.ApplicationFlags.HANDLES_OPEN | Gio.ApplicationFlags.HANDLES_COMMAND_LINE }); -// Checking if a flag is set, and removing it if so -if (myApp.flags & Gio.ApplicationFlags.HANDLES_OPEN) +if (myApp.flags & Gio.ApplicationFlags.HANDLES_OPEN) { myApp.flags &= ~Gio.ApplicationFlags.HANDLES_OPEN; +} ``` [gjs-docs]: https://gjs-docs.gnome.org @@ -270,74 +208,38 @@ ## Structs and Unions -Structures and unions are documented in the [GNOME API documentation][gjs-docs] -(e.g. [Gdk.Event][gdk-event]) and generally have either JavaScript properties or -getter methods for each member. Results may vary when trying to modify structs -or unions. - -An example from GTK3: +C structures and unions are documented in the [GNOME API documentation][gjs-docs] (e.g. [Gdk.Event][gdk-event]) and generally have either JavaScript properties or getter methods for each member. Results may vary when trying to modify structs or unions. ```js -widget.connect('key-press-event', (widget, event) => { - // expected output: [union instance proxy GIName:Gdk.Event jsobj@0x7f19a00b6400 native@0x5620c6a7c6e0] +widget.connect("key-press-event", (widget, event) => { log(event); - - // expected output: true + // expected output: [union instance proxy GIName:Gdk.Event jsobj@0x7f19a00b6400 native@0x5620c6a7c6e0] log(event.get_event_type() === Gdk.EventType.KEY_PRESS); - - // example output: 65507 - const [, keyval] = event.get_keyval(); + // expected output: true + let [ok, keyval] = event.get_keyval(); log(keyval); + // example output: 65507 }); ``` [gdk-event]: https://gjs-docs.gnome.org/gdk40/gdk.event -## Return Values and `caller-allocates` - -> Note: This information is intended for C programmers. Most developers can -> simply check the documentation for the function in question. +## Multiple return values (caller-allocates) -In GJS functions with "out" parameters (`caller-allocates`) are returned as an -array of values. For example, in C you may use function like this: - -```c -GtkRequisition min_size, max_size; - -gtk_widget_get_preferred_size (widget, &min_size, &max_size); -``` - -While in GJS it is returned as an array of those values instead: +In GJS caller-allocates (variables passed into a function) and functions with multiple out parameters are returned as an array of return values. If the function has a return value, it will be the first element of that array. ```js -const [minSize, maxSize] = widget.get_preferred_size(); -``` - -If the function has both a return value and "out" parameters, the return value -will be the first element of the array: - -```js -try { - const file = new Gio.File({ path: '/proc/cpuinfo' }); +let [minimumSize, naturalSize] = label.get_preferred_size(); - // In the C API, `ok` is the only return value of this method - const [ok, contents, etag_out] = file.load_contents(null); -} catch(e) { - log('Failed to read file: ' + e.message); -} -``` - -Note that because JavaScript throws exceptions, rather than setting a `GError` -structure, it is common practice to elide the success boolean in GJS: - -```js +// Functions with boolean 'success' returns often still throw an Error on failure try { - const file = new Gio.File({ path: '/proc/cpuinfo' }); - - // Eliding success boolean - const [, contents, etag] = file.load_contents(null); + let file = new Gio.File({ path: '/proc/cpuinfo' }); + let [ok, contents, etag_out] = file.load_contents(null); + // "ok" is actually useless in this scenario, since if it is false, + // an exception will have been thrown. You can skip return values + // you don't want with array elision: + let [, contents2] = file.load_contents(null); } catch(e) { log('Failed to read file: ' + e.message); } ``` - diff -Nru gjs-1.74.0/doc/Modules.md gjs-1.72.2/doc/Modules.md --- gjs-1.74.0/doc/Modules.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Modules.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,24 +1,343 @@ -# Modules +GJS includes some built-in modules, as well as helpers for some core APIs like DBus like Variants. The headings below are links to the JavaScript source, which are decently documented and informative of usage. -The documentation previously found here has been updated and reorganized. Most -of the documentation can now be browsed at https://gjs-docs.gnome.org. +## [Gio](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/Gio.js) -* [Overrides](Overrides.md) - * [GObject](Overrides.md#gobject) - * [Gio](Overrides.md#gio) - * [GLib](Overrides.md#glib) - * [GObject-Introspection](Overrides.md#gobject-introspection) -* Built-In Modules - * [Cairo](cairo.md) - * [Format](Format.md) - * [Gettext](Gettext.md) - * [Mainloop](Mainloop.md) - * [Package Specification](Package/Specification.md) - * [Signals](Signals.md) - * [System](System.md) -* Deprecated Modules - * [ByteArray](ByteArray.md) (see [Encoding](Encoding.md)) - * [Lang](Lang.md) (see [GObject](Overrides.md#gobject)) - * [jsUnit](Testing.md#jsunit) (see [Jasmine](Testing.md#jasmine-gjs)) - * [Tweener](http://hosted.zeh.com.br/tweener/docs/) +**Import with `const Gio = gi.require('Gio');` or `import Gio from 'gi://Gio'`** +The `Gio` override includes a number of utilities for DBus that will be documented further at a later date. Below is a reasonable overview. + +* `Gio.DBus.session`, `Gio.DBus.system` + + Convenience properties that wrap `Gio.bus_get_sync()` to return a DBus connection +* `Gio.DBusNodeInfo.new_for_xml(xmlString)` + + Return a new `Gio.DBusNodeInfo` for xmlString +* `Gio.DBusInterfaceInfo.new_for_xml(xmlString)` + + Return a new `Gio.DBusInterfaceInfo` for the first interface node of xmlString +* `Gio.DBusProxy.makeProxyWrapper(xmlString)` + + Returns a `function(busConnection, busName, objectPath, asyncCallback, cancellable)` which can be called to return a new `Gio.DBusProxy` for the first interface node of `xmlString`. See [here][old-dbus-example] for the original example. +* `Gio.DBusExportedObject.wrapJSObject(Gio.DbusInterfaceInfo, jsObj)` + + Takes `jsObj`, an object instance implementing the interface described by `Gio.DbusInterfaceInfo`, and returns an implementation object with these methods: + + * `export(busConnection, objectPath)` + * `unexport()` + * `unexport_from_connection(busConnection)` + * `flush()` + * `emit_signal(name, variant)` + * `emit_property_changed(name, variant)` + +[old-dbus-example]: https://wiki.gnome.org/Gjs/Examples/DBusClient + +## [GLib](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/GLib.js) + +**Import with `const GLib = gi.require('GLib');` or `import GLib from 'gi://GLib'`** + +Mostly GVariant and GBytes compatibility. + +* `GLib.log_structured()`: Wrapper for g_log_variant() +* `GLib.Bytes.toArray()`: Convert a GBytes object to a ByteArray object +* `GLib.Variant.unpack()`: Unpack a variant to a native type +* `GLib.Variant.deep_unpack()`: Deep unpack a variant. + +## [GObject](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/GObject.js) + +**Import with `const GObject = gi.require('GObject');` or `import GObject from 'gi://GObject'`** + +Mostly GObject implementation (properties, signals, GType mapping). May be useful as a reference. + +## [Gtk](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/Gtk.js) + +**Import with `const Gtk = gi.require('Gtk', '3.0');` or `import Gtk from 'gi://Gtk'`** + +Mostly GtkBuilder/composite template implementation. May be useful as a reference. + +>>> +**REMINDER:** You should specify a version prior to importing a library with multiple versions: + +```js +import Gtk from 'gi://Gtk?version=3.0'; +``` +>>> + +## Cairo + +**Import with `import Cairo from 'cairo';`** + +Mostly API compatible with [cairo](https://www.cairographics.org/documentation/), but using camelCase function names. There is list of constants in [cairo.js][cairo-const] and functions for each object in its corresponding C++ file (eg. [cairo-context.cpp][cairo-func]). A simple example drawing a 32x32 red circle: + +```js +import Gtk from 'gi://Gtk?version=3.0'; +import Cairo from 'cairo'; + +let drawingArea = new Gtk.DrawingArea({ + height_request: 32, + width_request: 32 +}); + +drawingArea.connect("draw", (widget, cr) => { + // Cairo in GJS uses camelCase function names + cr.setSourceRGB(1.0, 0.0, 0.0); + cr.setOperator(Cairo.Operator.DEST_OVER); + cr.arc(16, 16, 16, 0, 2*Math.PI); + cr.fill(); + // currently when you connect to a draw signal you have to call + // cr.$dispose() on the Cairo context or the memory will be leaked. + cr.$dispose(); + return false; +}); +``` + +[cairo-const]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/cairo.js +[cairo-func]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/cairo-context.cpp#L825 + +## [Format](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/format.js) + +**Import with `const Format = imports.format;`** + +The format import is mostly obsolete, providing `vprintf()`, `printf()` and `format()`. Native [template literals][template-literals] should be preferred now, except in few situations like Gettext (See [Bug #50920][bug-50920]). + +```js +let foo = "Pi"; +let bar = 1; +let baz = Math.PI; + +// Using native template literals (Output: Pi to 2 decimal points: 3.14) +`${foo} to ${bar*2} decimal points: ${baz.toFixed(bar*2)}` + +// Applying format() to the string prototype +const Format = imports.format; +String.prototype.format = Format.format; + +// Using format() (Output: Pi to 2 decimal points: 3.14) +"%s to %d decimal points: %.2f".format(foo, bar*2, baz); + +// Using format() with Gettext +_("%d:%d").format(11, 59); +Gettext.ngettext("I have %d apple", "I have %d apples", num).format(num); + +``` + +[template-literals]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals +[bug-50920]: https://savannah.gnu.org/bugs/?50920 + +## [Gettext](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/gettext.js) + +**Import with `import gettext from 'gettext';`** + +Helper functions for gettext. See also [examples/gettext.js][example-gettext] for usage. + +[example-gettext]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/examples/gettext.js + +### Legacy Imports (`imports.gettext`) + +Gettext is also exposed via `imports.gettext` on the global `imports` object. + +## [jsUnit](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/jsUnit.js) + +**DEPRECATED** + +Deprecated unit test functions. [Jasmine][jasmine-gjs] for GJS should now be preferred, as demonstrated in the GJS [test suite][gjs-tests]. + +[jasmine-gjs]: https://github.com/ptomato/jasmine-gjs +[gjs-tests]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/installed-tests/js + +## [`Lang`](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/lang.js) + +**DEPRECATED** + +Lang is a mostly obsolete library, that should only be used in cases where older versions of GJS must be supported. For example, `Lang.bind()` was necessary to bind `this` to the function context before the availability of arrow functions: + +```js +const Lang = imports.lang; +const FnorbLib = imports.fborbLib; + +const MyLegacyClass = new Lang.Class({ + _init: function() { + let fnorb = new FnorbLib.Fnorb(); + fnorb.connect('frobate', Lang.bind(this, this._onFnorbFrobate)); + }, + + _onFnorbFrobate: function(fnorb) { + this._updateFnorb(); + } +}); + +var MyNewClass = class { + constructor() { + let fnorb = new FnorbLib.Fnorb(); + fnorb.connect('frobate', fnorb => this._onFnorbFrobate); + } + + _onFnorbFrobate(fnorb) { + this._updateFnorb(); + } +} +``` + +## [Mainloop](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/mainloop.js) + +**DEPRECATED** + +Mainloop is simply a layer of convenience and backwards-compatibility over some GLib functions (such as [`GLib.timeout_add()`][gjs-timeoutadd] which in GJS is mapped to [`g_timeout_add_full()`][c-timeoutaddfull]). It's use is not generally recommended anymore. + +[c-timeoutaddfull]: https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add-full +[gjs-timeoutadd]: https://gjs-docs.gnome.org/glib20/glib.timeout_add + +## [Package](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/package.js) + +Infrastructure and utilities for [standalone applications](Home#standalone-applications). + +## [Signals](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/signals.js) + +**Import with `const Signals = imports.signals;`** + +A GObject-like signal framework for native Javascript objects. + +**NOTE:** Unlike [GObject signals](Mapping#signals), `this` within a signal callback will refer to the global object (ie. `globalThis`). + +```js +const Signals = imports.signals; + +var MyJSClass = class { + testSignalEmission () { + this.emit("exampleSignal", "stringArg", 42); + } +} +Signals.addSignalMethods(MyJSClass.prototype); + +let obj = new MyJSObject(); + +// Connect and disconnect like standard GObject signals +let handlerId = obj.connect("exampleSignal", (obj, stringArg, intArg) => { + // Remember 'this' === 'globalThis' +}); +obj.disconnect(handlerId); + +// A convenience function not in GObject +obj.disconnectAll(); +``` + +## [System](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/system.cpp) + +**Import with `import system from 'system';`** + +The System module offers a number of useful functions and properties for debugging and shell interaction (eg. ARGV): + + * `addressOf(object)` + + Return the memory address of any object as a string in hexadecimal, e.g. `0xb4f170f0`. + Caution, don't use this as a unique identifier! + JavaScript's garbage collector can move objects around in memory, or deduplicate identical objects, so this value may change during the execution of a program. + + * `refcount(gobject)` + + Return the reference count of any GObject-derived type (almost any class from GTK, Clutter, GLib, Gio, etc.). When an object's reference count is zero, it is cleaned up and erased from memory. + + * `breakpoint()` + + This is the real gem of the System module! It allows just the tiniest amount of decent debugging practice in GJS. Put `System.breakpoint()` in your code and run it under GDB like so: + + ``` + gdb --args gjs my_program.js + ``` + + When GJS reaches the breakpoint, it will stop executing and return you to the GDB prompt, where you can examine the stack or other things, or type `cont` to continue running. Note that if you run the program outside of GDB, it will abort at the breakpoint, so make sure to remove the breakpoint when you're done debugging. + + * `gc()` + + Run the garbage collector. + + * `exit(error_code)` + + This works the same as C's `exit()` function; exits the program, passing a certain error code to the shell. The shell expects the error code to be zero if there was no error, or non-zero (any value you please) to indicate an error. This value is used by other tools such as `make`; if `make` calls a program that returns a non-zero error code, then `make` aborts the build. + + * `version` + + This property contains version information about GJS. + + * `programInvocationName` + + This property contains the name of the script as it was invoked from the command line. In C and other languages, this information is contained in the first element of the platform's equivalent of `argv`, but GJS's `ARGV` only contains the subsequent command-line arguments, so `ARGV[0]` in GJS is the same as `argv[1]` in C. + + For example, passing ARGV to a `Gio.Application`/`Gtk.Application` (See also: + [examples/gtk-application.js][example-application]): + + ```js + import Gtk from 'gi://Gtk?version=3.0'; + import system from 'system'; + + let myApp = new Gtk.Application(); + myApp.connect("activate", () => log("activated")); + myApp.run([System.programInvocationName].concat(ARGV)); + ``` + +[example-application]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/examples/gtk-application.js + +## [Tweener](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/script/tweener/) + +**Import with `const Tweener = imports.tweener.tweener;`** + +Built-in version of the well-known [Tweener][tweener-www] animation/property transition library. + +[tweener-www]: http://hosted.zeh.com.br/tweener/docs/ + +## GObject Introspection + +**Import with `import gi from 'gi';`** + +A wrapper of **libgirepository** to import native gobject-introspection libraries. + +* `gi.require(library: string, version?: string)` + +Loads a native gobject-introspection library. +Version is required if more than one version of a library is installed. + +You can also import libraries through the `gi://` URL scheme. +This function is only intended to be used when you want to import a +library conditionally, since top-level import statements are resolved +statically. + +### Legacy Imports (`imports.gi`) + +**Import with `const gi = imports.gi;`** + +A wrapper for **libgirepository** is also available via the global `imports` object. +This object has a property `versions` which is an object on which you can set string-valued +properties indicating the version of that gobject-introspection library you want to load, +and loading multiple versions in the same process is forbidden. So if you want to +use gtk-3.0, set `imports.gi.versions.Gtk = '3.0';`. + +Any other properties of `imports.gi` will attempt to import a gobject-introspection library +with the property name, picking the latest version if there is no entry for it in `imports.gi.versions`. + +## Legacy Imports + +Prior to the introduction of [ES Modules](ESModules.md), GJS had its own import system. + +**imports** is a global object that you can use to import any js file or GObject +Introspection lib as module, there are 4 special properties of **imports**: + + * `searchPath` + + An array of path that used to look for files, if you want to prepend a path + you can do something like `imports.searchPath.unshift(myPath)`. + + * `__modulePath__` + * `__moduleName__` + * `__parentModule__` + + These 3 properties is intended to be used internally, you should not use them. + +Any other properties of **imports** is treated as a module, if you access these +properties, an import is attempted. Gjs try to look up a js file or directory by property name +from each location in `imports.searchPath`. For `imports.foo`, if a file named +`foo.js` is found, this file is executed and then imported as a module object; else if +a directory `foo` is found, a new importer object is returned and its `searchPath` property +is replaced by the path of `foo`. + +Note that any variable, function and class declared at the top level, +except those declared by `let` or `const`, are exported as properties of the module object, +and one js file is executed only once at most even if it is imported multiple times. diff -Nru gjs-1.74.0/doc/Overrides.md gjs-1.72.2/doc/Overrides.md --- gjs-1.74.0/doc/Overrides.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Overrides.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,806 +0,0 @@ -# Overrides - -Like other binding languages, GJS includes a number of overrides for various -libraries, like GIO and GTK. These overrides include implementations of -functions not normally available to language bindings, as well as convenience -functions and support for native JavaScript features such as iteration. - -The library headings below are links to the JavaScript source for each override, -which may clarify particular behaviour or contain extra implementation notes. - - -## [Gio](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/Gio.js) - -The `Gio` override includes a number of utilities and conveniences, in -particular a number of helpers for working with D-Bus in GJS. - -For a longer introduction to the D-Bus utilities listed here, see the -[D-Bus Tutorial][dbus-tutorial]. - -[dbus-tutorial]: https://gjs.guide/guides/gio/dbus.html - -### Gio.DBus.session - -> Warning: It is a programmer error to call `close()` on this object instance - -Type: -* [`Gio.DBusConnection`][gdbusconnection] - -Convenience for getting the session [`Gio.DBusConnection`][gdbusconnection]. -This always returns the same object and is equivalent to calling: - -```js -const connection = Gio.bus_get_sync(Gio.BusType.SESSION, null); -``` - -[gdbusconnection]: https://gjs-docs.gnome.org/gio20/gio.dbusconnection - -### Gio.DBus.system - -> Warning: It is a programmer error to call `close()` on this object instance - -Type: -* [`Gio.DBusConnection`][gdbusconnection] - -Convenience for getting the system [`Gio.DBusConnection`][gdbusconnection]. -This always returns the same object and is equivalent to calling: - -```js -const connection = Gio.bus_get_sync(Gio.BusType.SYSTEM, null); -``` - -[gdbusconnection]: https://gjs-docs.gnome.org/gio20/gio.dbusconnection - -### Gio.DBusNodeInfo.new_for_xml(xmlData) - -Type: -* Static - -Parameters: -* xmlData (`String`) — Valid D-Bus introspection XML - -Returns: -* (`Gio.DBusNodeInfo`) — A [`Gio.DBusNodeInfo`][gdbusnodeinfo] structure - -> Note: This is an override for function normally available in GIO - -Parses `xmlData` and returns a [`Gio.DBusNodeInfo`][gdbusnodeinfo] representing -the data. - -The introspection XML must contain exactly one top-level `` element. - -Note that this routine is using a GMarkup-based parser that only accepts a -subset of valid XML documents. - -[gdbusnodeinfo]: https://docs.gtk.org/gio/struct.DBusNodeInfo.html - -### Gio.DBusInterfaceInfo.new_for_xml(xmlData) - -Type: -* Static - -Parameters: -* xmlData (`String`) — Valid D-Bus introspection XML - -Returns: -* (`Gio.DBusInterfaceInfo`) — A [`Gio.DBusInterfaceInfo`][gdbusinterfaceinfo] - structure - -Parses `xmlData` and returns a [`Gio.DBusInterfaceInfo`][gdbusinterfaceinfo] -representing the first `` element of the data. - -This is a convenience wrapper around `Gio.DBusNodeInfo.new_for_xml()` for the -common case of a [`Gio.DBusNodeInfo`][gdbusnodeinfo] with a single interface. - -[gdbusinterfaceinfo]: https://gjs-docs.gnome.org/gio20/gio.dbusinterfaceinfo - -### Gio.DBusProxy.makeProxyWrapper(interfaceInfo) - -Type: -* Static - -Parameters: -* interfaceInfo (`String`|`Gio.DBusInterfaceInfo`) — Valid D-Bus introspection - XML or [`Gio.DBusInterfaceInfo`][gdbusinterfaceinfo] structure - -Returns: -* (`Function`) — A `Function` used to create a [`Gio.DBusProxy`][gdbusproxy] - -Returns a `Function` that can be used to create a [`Gio.DBusProxy`][gdbusproxy] -for `interfaceInfo` if it is a [`Gio.DBusInterfaceInfo`][gdbusinterfaceinfo] -structure, or the first `` element if it is introspection XML. - -The returned `Function` has the following signature: - -```js -@param {Gio.DBusConnection} bus — A bus connection -@param {String} name — A well-known name -@param {String} object — An object path -@param {Function} [asyncCallback] — Optional callback -@param {Gio.Cancellable} [cancellable] — Optional cancellable -@param {Gio.DBusProxyFlags} flags — Optional flags -``` - -The signature for `asyncCallback` is: - -```js -@param {Gio.DBusProxy|null} proxy — A D-Bus proxy, or null on failure -@param {Error} error — An exception, or null on success -``` - -See the [D-Bus Tutorial][make-proxy-wrapper] for an example of how to use this -function and the resulting [`Gio.DBusProxy`][gdbusproxy]. - -[gdbusproxy]: https://gjs-docs.gnome.org/gio20/gio.dbusproxy -[make-proxy-wrapper]: https://gjs.guide/guides/gio/dbus.html#high-level-proxies - -### Gio.DBusExportedObject.wrapJSObject(interfaceInfo, jsObj) - -Type: -* Static - -Parameters: -* interfaceInfo (`String`|`Gio.DBusInterfaceInfo`) — Valid D-Bus introspection - XML or [`Gio.DBusInterfaceInfo`][gdbusinterfaceinfo] structure -* jsObj (`Object`) — A `class` instance implementing `interfaceInfo` - -Returns: -* (`Gio.DBusInterfaceSkeleton`) — A [`Gio.DBusInterfaceSkeleton`][gdbusinterfaceskeleton] - -Takes `jsObj`, an object instance implementing the interface described by -[`Gio.DBusInterfaceInfo`][gdbusinterfaceinfo], and returns an instance of -[`Gio.DBusInterfaceSkeleton`][gdbusinterfaceskeleton]. - -The returned object has two additional methods not normally found on a -`Gio.DBusInterfaceSkeleton` instance: - -* `emit_property_changed(propertyName, propertyValue)` - * propertyName (`String`) — A D-Bus property name - * propertyValue (`GLib.Variant`) — A [`GLib.Variant`][gvariant] - -* `emit_signal(signalName, signalParameters)` - * signalName (`String`) — A D-Bus signal name - * signalParameters (`GLib.Variant`) — A [`GLib.Variant`][gvariant] - -See the [D-Bus Tutorial][wrap-js-object] for an example of how to use this -function and the resulting [`Gio.DBusInterfaceSkeleton`][gdbusinterfaceskeleton]. - -[gdbusinterfaceskeleton]: https://gjs-docs.gnome.org/gio20/gio.dbusinterfaceskeleton -[gvariant]: https://gjs-docs.gnome.org/glib20/glib.variant -[wrap-js-object]: https://gjs.guide/guides/gio/dbus.html#exporting-interfaces - -### Gio._promisify(prototype, startFunc, finishFunc) - -> Warning: This is a tech-preview and not guaranteed to be stable - -Type: -* Static - -Parameters: -* prototype (`Object`) — The prototype of a GObject class -* startFunc (`Function`) — The "async" or "start" method -* finishFunc (`Function`) — The "finish" method - -Replaces the original `startFunc` on a GObject class prototype, so that it -returns a `Promise` and can be used as a JavaScript `async` function. - -The function may then be used like any other `Promise` without the need for a -customer wrapper, simply by invoking `startFunc` without the callback argument: - -```js -Gio._promisify(Gio.InputStream.prototype, 'read_bytes_async', - 'read_bytes_finish'); - -try { - const inputStream = new Gio.UnixInputStream({fd: 0}); - const bytes = await inputStream.read_bytes_async(4096, - GLib.PRIORITY_DEFAULT, null); -} catch (e) { - logError(e, 'Failed to read bytes'); -} -``` - - -## [GLib](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/GLib.js) - -The `GLib` override includes a number of utilities and conveniences for working -with [`GLib.Variant`][gvariant], [`GLib.Bytes`][gbytes] and others. - -See the [GVariant Tutorial][make-proxy-wrapper] for examples of working with -[`GLib.Variant`][gvariant] objects and the functions here. - -### GLib.Bytes.toArray() - -Returns: -* (`Uint8Array`) — A `Uint8Array` - -Convert a [`GLib.Bytes`][gbytes] object to a `Uint8Array` object. - -[gbytes]: https://gjs-docs.gnome.org/glib20/glib.bytes - -### GLib.log_structured(logDomain, logLevel, stringFields) - -> Note: This is an override for function normally available in GLib - -Type: -* Static - -Parameters: -* logDomain (`String`) — A log domain, usually G_LOG_DOMAIN -* logLevel (`GLib.LogLevelFlags`) — A log level, either from - [`GLib.LogLevelFlags`][gloglevelflags], or a user-defined level -* stringFields (`{String: Any}`) — Key–value pairs of structured data to add to - the log message - -Log a message with structured data. - -For more information about this function, see the upstream documentation -for [g_log_structured()][glogstructured]. - -[glogdomain]: https://gjs-docs.gnome.org/glib20/glib.log_domain -[gloglevelflags]: https://gjs-docs.gnome.org/glib20/glib.loglevelflags -[glogstructured]: https://docs.gtk.org/glib/func.log_structured.html - -### GLib.Variant.unpack() - -Returns: -* (`Any`) — A native JavaScript value, corresponding to the type of variant - -A convenience for unpacking a single level of a [`GLib.Variant`][gvariant]. - -### GLib.Variant.deepUnpack() - -Returns: -* (`Any`) — A native JavaScript value, corresponding to the type of variant - -A convenience for unpacking a [`GLib.Variant`][gvariant] and its children, but -only up to one level. - -### GLib.Variant.recursiveUnpack() - -Returns: -* (`Any`) — A native JavaScript value, corresponding to the type of variant - -A convenience for recursively unpacking a [`GLib.Variant`][gvariant] and all its -descendants. - -Note that this method will unpack source values (e.g. `uint32`) to native values -(e.g. `Number`), so some type information may not be fully represented in the -result. - - -## [GObject](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/GObject.js) - -> See also: The [Mapping][mapping] documentation, for general GObject usage - -The `GObject` override mostly provides aliases for constants and types normally -found in GObject, as well as [`GObject.registerClass()`](#gobject-registerclass) -for registering subclasses. - -[mapping]: https://gjs-docs.gnome.org/gjs/mapping.md - -### GObject.Object.$gtype - -> See also: [GType Objects][gtype-objects] - -Type: -* `GObject.Type` - -The `GObject.Type` object for the given type. - -This is the proper way to find the GType given an object instance or a class. -For a class, [`GObject.type_from_name()`][gtypefromname] can also be used. - -```js -// expected output: [object GType for 'GObject'] - -// GType for an object class -log(GObject.Object.$gtype); - -// GType for an object instance -const objectInstance = GObject.Object.new() -log(objectInstance.constructor.$gtype); - -// GType from C type name -log(GObject.type_from_name('GObject')); -``` - -Note that the GType name for user-defined subclasses will be prefixed with -`Gjs_` (i.e. `Gjs_MyObject`), unless the `GTypeName` class property is specified -when calling [`GObject.registerClass()`](#gobject-registerclass). - -[gtypefromname]: https://gjs-docs.gnome.org/gobject20/gobject.type_from_name -[gtype-objects]: https://gjs-docs.gnome.org/gjs/mapping.md#gtype-objects - -### GObject.registerClass(metaInfo, klass) - -Type: -* Static - -Parameters: -* metaInfo (`Object`) — An optional dictionary of class properties -* klass (`class`) — A JavaScript class expression - -Returns: -* (`GObject.Class`) — A registered `GObject.Class` - -Registers a JavaScript class expression with the GObject type system. This -function supports both a two-argument and one-argument form. - -In the two-argument form, the first argument is an object with meta info such as -properties and signals. The second argument is the class expression for the -class itself. - -```js -var MyObject = GObject.registerClass({ - GTypeName: 'MyObject', - Properties: { ... }, - Signals: { ... }, -}, class MyObject extends GObject.Object { - constructor() { ... } -}); -``` - -In the one-argument form, the meta info object is omitted and only the class -expression is required. - -```js -var MyObject = GObject.registerClass( -class MyObject extends GObject.Object { - constructor() { ... } -}); -``` - -See the [GObject Tutorial][gobject-subclassing] for examples of subclassing -GObject and declaring class properties. - -[gobject-subclassing]: https://gjs.guide/guides/gobject/subclassing.html#subclassing-gobject - -### GObject.ParamSpec - -The `GObject` override contains aliases for the various `GParamSpec` types, -which are used when defining properties for a subclass. Be aware that the -arguments for `flags` and default values are reversed: - -```js -// Original function -const pspec1 = GObject.param_spec_boolean('property1', 'nick', 'blurb', - true, // default value - GObject.ParamFlags.READABLE); // flags - -// GJS alias -const pspec2 = GObject.ParamSpec.boolean('property2', 'nick', 'blurb', - GObject.ParamFlags.READABLE, // flags - true); // default value -``` - -### GObject Signal Matches - -This is an object passed to a number of signal matching functions. It has three -properties: - -* signalId (`Number`) — A signal ID. Note that this is the signal ID, not a - handler ID as returned from `GObject.Object.connect()`. -* detail (`String`) — A signal detail, such as `prop` in `notify::prop`. -* func (`Function`) — A signal callback function. - -For example: - -```js -// Note that `Function.prototype.bind()` creates a new function instance, so -// you must pass the correct instance to successfully match a handler -function notifyCallback(obj, pspec) { - log(pspec.name); -} - -const objectInstance = new GObject.Object(); -const handlerId = objectInstance.connect('notify::property-name', - notifyCallback); - -const result = GObject.signal_handler_find(objectInstance, { - detail: 'property-name', - func: notifyCallback, -}); - -console.assert(result === handlerId); -``` - -### GObject.Object.connect(name, callback) - -> See also: [GObject Signals Tutorial][gobject-signals-tutorial] - -Parameters: -* name (`String`) — A detailed signal name -* callback (`Function`) — A callback function - -Returns: -* (`Number`) — A signal handler ID - -Connects a callback function to a signal for a particular object. - -The first argument of the callback will be the object emitting the signal, while -the remaining arguments are the signal parameters. - -The handler will be called synchronously, before the default handler of the -signal. `GObject.Object.emit()` will not return control until all handlers are -called. - -For example: - -```js -// A signal connection (emitted when any property changes) -let handler1 = obj.connect('notify', (obj, pspec) => { - log(`${pspec.name} changed on ${obj.constructor.$gtype.name} object`); -}); - -// A signal name with detail (emitted when "property-name" changes) -let handler2 = obj.connect('notify::property-name', (obj, pspec) => { - log(`${pspec.name} changed on ${obj.constructor.$gtype.name} object`); -}); -``` - -[gobject-signals-tutorial]: https://gjs.guide/guides/gobject/basics.html#signals - -### GObject.Object.connect_after(name, callback) - -> See also: [GObject Signals Tutorial][gobject-signals-tutorial] - -Parameters: -* name (`String`) — A detailed signal name -* callback (`Function`) — A callback function - -Returns: -* (`Number`) — A signal handler ID - -Connects a callback function to a signal for a particular object. - -The first argument of the callback will be the object emitting the signal, while -the remaining arguments are the signal parameters. - -The handler will be called synchronously, after the default handler of the -signal. - -[gobject-signals-tutorial]: https://gjs.guide/guides/gobject/basics.html#signals - -### GObject.Object.disconnect(id) - -> See also: [GObject Signals Tutorial][gobject-signals-tutorial] - -Parameters: -* id (`Number`) — A signal handler ID - -Disconnects a handler from an instance so it will not be called during any -future or currently ongoing emissions of the signal it has been connected to. - -The `id` has to be a valid signal handler ID, connected to a signal of the -object. - -For example: - -```js -let handlerId = obj.connect('notify', (obj, pspec) => { - log(`${pspec.name} changed on ${obj.constructor.$gtype.name} object`); -}); - -if (handlerId) { - obj.disconnect(handlerId); - handlerId = null; -} -``` - -[gobject-signals-tutorial]: https://gjs.guide/guides/gobject/basics.html#signals - -### GObject.Object.emit(name, ...args) - -> See also: [GObject Signals Tutorial][gobject-signals-tutorial] - -Parameters: -* name (`String`) — A detailed signal name -* args (`Any`) — Signal parameters - -Returns: -* (`Any`|`undefined`) — Optional return value - -Emits a signal. Signal emission is done synchronously. The method will only -return control after all handlers are called or signal emission was stopped. - -In some cases, signals expect a return value (usually a `Boolean`). The effect -of the return value will be described in the documentation for the signal. - -For example: - -```js -// Emitting a signal -obj.emit('signal-name', arg1, arg2); - -// Emitting a signal that returns a boolean -if (obj.emit('signal-name', arg1, arg2)) - log('signal emission was handled!'); -else - log('signal emission was unhandled!'); -``` - -[gobject-signals-tutorial]: https://gjs.guide/guides/gobject/basics.html#signals - -### GObject.signal_handler_find(instance, match) - -> Note: This function has a different signature that the original - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* match (`Object`) — A dictionary of properties to match - -Returns: -* (`Number`|`BigInt`|`Object`|`null`) — A valid non-0 signal handler ID for a - successful match. - -Finds the first signal handler that matches certain selection criteria. - -The criteria are passed as properties of a match object. The match object has to -be non-empty for successful matches. If no handler was found, a falsy value is -returned. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### GObject.signal_handlers_block_matched(instance, match) - -> Note: This function has a different signature that the original - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* match (`Object`) — A dictionary of properties to match - -Returns: -* (`Number`) — The number of handlers that matched. - -Blocks all handlers on an instance that match certain selection criteria. - -The criteria are passed as properties of a match object. The match object has to -have at least `func` for successful matches. If no handlers were found, 0 is -returned, the number of blocked handlers otherwise. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### GObject.signal_handlers_unblock_matched(instance, match) - -> Note: This function has a different signature that the original - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* match (`Object`) — A dictionary of properties to match - -Returns: -* (`Number`) — The number of handlers that matched. - -Unblocks all handlers on an instance that match certain selection criteria. - -The criteria are passed as properties of a match object. The match object has to -have at least `func` for successful matches. If no handlers were found, 0 is -returned, the number of blocked handlers otherwise. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### GObject.signal_handlers_disconnect_matched(instance, match) - -> Note: This function has a different signature that the original - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* match (`Object`) — A dictionary of properties to match - -Returns: -* (`Number`) — The number of handlers that matched. - -Disconnects all handlers on an instance that match certain selection criteria. - -The criteria are passed as properties of a match object. The match object has to -have at least `func` for successful matches. If no handlers were found, 0 is -returned, the number of blocked handlers otherwise. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### GObject.signal_handlers_block_by_func(instance, func) - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* func (`Function`) — The callback function - -Returns: -* (`Number`) — The number of handlers that matched. - -Blocks all handlers on an instance that match `func`. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### GObject.signal_handlers_unblock_by_func(instance, func) - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* func (`Function`) — The callback function - -Returns: -* (`Number`) — The number of handlers that matched. - -Unblocks all handlers on an instance that match `func`. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### GObject.signal_handlers_disconnect_by_func(instance, func) - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* func (`Function`) — The callback function - -Returns: -* (`Number`) — The number of handlers that matched. - -Disconnects all handlers on an instance that match `func`. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### GObject.signal_handlers_disconnect_by_data(instance, data) - -> Warning: This function does not work in GJS - -Type: -* Static - -Parameters: -* instance (`GObject.Object`) — A [`GObject.Object`][gobject] instance -* data (`void`) — The callback data - -Returns: -* (`Number`) — The number of handlers that matched. - -Disconnects all handlers on an instance that match `data`. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - - -## [Gtk](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/Gtk.js) - -Mostly GtkBuilder/composite template implementation. May be useful as a reference. - -> Reminder: You should specify a version prior to importing a library with -> multiple versions. - -```js -// GTK3 -import Gtk from 'gi://Gtk?version=3.0'; - -// GTK4 -import Gtk from 'gi://Gtk?version=4.0'; -``` - -### Gtk.Container.list_child_properties(widget) - -> Note: This GTK3 function requires different usage in GJS than other languages - -Type: -* Static - -Parameters: -* widget (`Gtk.Container`) — A [`Gtk.Container`][gtkcontainer] - -Returns: -* (`Array(GObject.ParamSpec)`) — A list of the container's child properties as - [`GObject.ParamSpec`][gparamspec] objects - -Returns all child properties of a container class. - -Note that in GJS, this is a static function on [`Gtk.Container`][gtkcontainer] -that must be called with `Function.prototype.call()`, either on a widget -instance or a widget class: - -```js -// Calling on a widget instance -const box = new Gtk.Box(); -const properties = Gtk.Container.list_child_properties.call(box); - -for (let pspec of properties) - log(pspec.name); - -// Calling on a widget class -const properties = Gtk.Container.list_child_properties.call(Gtk.Box); - -for (let pspec of properties) - log(pspec.name); -``` - -For more information about this function, see the upstream documentation -for [gtk_container_class_list_child_properties()][gtkcontainerclasslistchildproperties]. - -[gtkwidget]: https://gjs-docs.gnome.org/gtk30/gtk.widget -[gtkcontainer]: https://gjs-docs.gnome.org/gtk30/gtk.container -[gtkcontainerclasslistchildproperties]: https://docs.gtk.org/gtk3/class_method.Container.list_child_properties.html -[gparamspec]: https://gjs-docs.gnome.org/gobject20/gobject.paramspec - - -## GObject Introspection - -> See also: [ECMAScript Modules][esmodules] - -The `gi` override is a wrapper for `libgirepository` for importing native -GObject-Introspection libraries. - -[esmodules]: https://gjs-docs.gnome.org/gjs/esmodules.md - -#### Import - -```js -import gi from 'gi'; -``` - -### gi.require(library, version) - -Type: -* Static - -Parameters: -* library (`String`) — A introspectable library -* version (`String`) — A library version, if applicable - -> New in GJS 1.72 (GNOME 42) - -Loads a native gobject-introspection library. -Version is required if more than one version of a library is installed. - -You can also import libraries through the `gi://` URL scheme. - -This function is only intended to be used when you want to import a library -conditionally, since top-level import statements are resolved statically. - - -## Legacy Imports - -Prior to the introduction of [ES Modules](ESModules.md), GJS had its own import -system. - -**imports** is a global object that you can use to import any js file or GObject -Introspection lib as module, there are 4 special properties of **imports**: - - * `searchPath` - - An array of path that used to look for files, if you want to prepend a path - you can do something like `imports.searchPath.unshift(myPath)`. - - * `__modulePath__` - * `__moduleName__` - * `__parentModule__` - - These 3 properties is intended to be used internally, you should not use - them. - -Any other properties of **imports** is treated as a module, if you access these -properties, an import is attempted. Gjs try to look up a js file or directory by -property name from each location in `imports.searchPath`. For `imports.foo`, if -a file named `foo.js` is found, this file is executed and then imported as a -module object; else if a directory `foo` is found, a new importer object is -returned and its `searchPath` property is replaced by the path of `foo`. - -Note that any variable, function and class declared at the top level, except -those declared by `let` or `const`, are exported as properties of the module -object, and one js file is executed only once at most even if it is imported -multiple times. - diff -Nru gjs-1.74.0/doc/Profiling.md gjs-1.72.2/doc/Profiling.md --- gjs-1.74.0/doc/Profiling.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Profiling.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,6 +1,6 @@ -# Profiling +# Profiling GJS -## Sysprof +## Profiling with Sysprof Typical profiling of JavaScript code is performed by passing the `--gjs` and `--no-perf` options: @@ -22,7 +22,7 @@ sysprof-cli --gjs --gtk -- gjs gtk.js ``` -#### See Also +### Additional Reading * Christian Hergert's [Blog Posts on Sysprof](https://blogs.gnome.org/chergert/category/sysprof/) diff -Nru gjs-1.74.0/doc/README.md gjs-1.72.2/doc/README.md --- gjs-1.74.0/doc/README.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -# GJS - -GJS is JavaScript bindings for the GNOME platform APIs. Powered by -Mozilla's [SpiderMonkey][spidermonkey] JavaScript engine and -[GObject Introspection][gobject-introspection], it opens the entire GNOME -ecosystem to JavaScript developers. - -The stable version of GJS is based on the latest Extended Support Release (ESR) -of SpiderMonkey. To find out when a language feature was added to GJS, review -[NEWS][gjs-news] in the GitLab repository. - -[gobject-introspection]: https://gi.readthedocs.io -[spidermonkey]: https://spidermonkey.dev/ -[gjs-news]: https://gitlab.gnome.org/GNOME/gjs/raw/HEAD/NEWS - -## Documentation - -If you are reading this file in the GJS repository, you may find it more -convenient to browse and search using the [API Documentation][gjs-docs] website -instead. There is documentation for GLib, GTK, Adwaita, WebKit, and many more -libraries. General documentation about built-in modules and APIs is under the -[GJS Topic](https://gjs-docs.gnome.org/gjs). - -[GJS Guide][gjs-guide] has many in-depth tutorials and examples for a number of -core GNOME APIs. The repository also has [code examples][gjs-examples] and -thorough coverage of language features in the [test suite][gjs-tests]. - -[GTK4 + GJS Book](https://rmnvgr.gitlab.io/gtk4-gjs-book/) is a start to finish -walkthrough for creating GTK4 applications with GJS. - -The [GNOME developer portal][gnome-developer] contains examples of a variety of -GNOME technologies written GJS, alongside other languages you may know. - -[gjs-docs]: https://gjs-docs.gnome.org/ -[gjs-examples]: https://gitlab.gnome.org/GNOME/gjs/tree/HEAD/examples -[gjs-tests]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/installed-tests/js -[gjs-guide]: https://gjs.guide -[gtk4-book]: https://rmnvgr.gitlab.io/gtk4-gjs-book/ -[gnome-developer]: https://developer.gnome.org/ - -## Applications - -GJS is a great option to write applications for the GNOME Desktop. - -The easiest way to get started is to use [GNOME Builder][gnome-builder], start a -new project and select `JavaScript` language. There is a also a -[package specification] and [template repository][template] available. - -[gnome-builder]: https://apps.gnome.org/app/org.gnome.Builder/ -[package specification]: https://gitlab.gnome.org/GNOME/gjs/-/blob/HEAD/doc/Package/Specification.md -[template]: https://github.com/gcampax/gtk-js-app - -GNOME Applications written in GJS: - -* [GNOME Characters](https://gitlab.gnome.org/GNOME/gnome-characters) -* [GNOME Documents](https://gitlab.gnome.org/GNOME/gnome-documents) -* [GNOME Maps](https://gitlab.gnome.org/GNOME/gnome-maps) -* [GNOME Sound Recorder](https://gitlab.gnome.org/GNOME/gnome-sound-recorder) -* [GNOME Weather](https://gitlab.gnome.org/GNOME/gnome-weather) -* [GNOME Books](https://gitlab.gnome.org/GNOME/gnome-books) -* [Polari](https://gitlab.gnome.org/GNOME/polari) IRC Client - -Third party applications written in GJS: - -* [Tangram](https://github.com/sonnyp/Tangram) -* [Quick Lookup](https://github.com/johnfactotum/quick-lookup) -* [Foliate](https://github.com/johnfactotum/foliate) -* [Marker](https://github.com/fabiocolacio/Marker) -* [Gnomit](https://github.com/small-tech/gnomit) -* [Clapper](https://github.com/Rafostar/clapper/) -* [Flatseal](https://github.com/tchx84/Flatseal) -* [Almond](https://github.com/stanford-oval/almond-gnome/) -* [Commit](https://github.com/sonnyp/commit/) -* [Junction](https://github.com/sonnyp/Junction) -* [Oh My SVG](https://github.com/sonnyp/OhMySVG) -* [Lobjur](https://github.com/ranfdev/Lobjur) -* [Touché](https://github.com/JoseExposito/touche) -* [Annex](https://github.com/andyholmes/annex) -* [Bolso](https://github.com/felipeborges/bolso) -* [Workbench](https://github.com/sonnyp/Workbench) - -### GNOME Shell Extensions - -GJS is used to write [GNOME Shell Extensions](https://extensions.gnome.org), -allowing anyone to make considerable modifications to the GNOME desktop. This -can also be a convenient way to prototype changes you may want to contribute to -the upstream GNOME Shell project. - -There is documentation and tutorials specifically for extension authors at -[gjs.guide/extensions](https://gjs.guide/extensions). - -### Embedding GJS - -GJS can also be embedded in other applications, such as with GNOME Shell, to -provide a powerful scripting language with support for the full range of -libraries with GObject-Introspection. - -## Getting Help - -* Discourse: https://discourse.gnome.org/ -* Chat: https://matrix.to/#/#javascript:gnome.org -* Issue Tracker: https://gitlab.gnome.org/GNOME/gjs/issues -* StackOverflow: https://stackoverflow.com/questions/tagged/gjs - diff -Nru gjs-1.74.0/doc/Signals.md gjs-1.72.2/doc/Signals.md --- gjs-1.74.0/doc/Signals.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Signals.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -## Signals - -The `Signals` module provides a GObject-like signal framework for native -JavaScript classes and objects. - -Example usage: - -```js -const Signals = imports.signals; - -// Apply signal methods to a class prototype -var ExampleObject = class { - emitExampleSignal () { - this.emit('exampleSignal', 'stringArg', 42); - } -} -Signals.addSignalMethods(ExampleObject.prototype); - -const obj = new ExampleObject(); - -// Connect to a signal -const handlerId = obj.connect('exampleSignal', (obj, stringArg, intArg) => { - // Note that `this` always refers `globalThis` in a Signals callback -}); - -// Disconnect a signal handler -obj.disconnect(handlerId); -``` - -#### Import - -> Attention: This module is not available as an ECMAScript Module - -The `Signals` module is available on the global `imports` object: - -```js -const Signals = imports.signals; -``` - -### Signals.addSignalMethods(object) - -Type: -* Static - -Parameters: -* object (`Object`) — A JavaScript object - -Applies the `Signals` convenience methods to an `Object`. - -Generally, this is called on an object prototype, but may also be called on an -object instance. - -### connect(name, callback) - -> Warning: Unlike GObject signals, `this` within a signal callback will always -> refer to the global object (ie. `globalThis`). - -Parameters: -* name (`String`) — A signal name -* callback (`Function`) — A callback function - -Returns: -* (`Number`) — A handler ID - -Connects a callback to a signal for an object. Pass the returned ID to -`disconect()` to remove the handler. - -If `callback` returns `true`, emission will stop and no other handlers will be -invoked. - -### disconnect(id) - -Parameters: -* id (`Number`) — The ID of the handler to be disconnected - -Disconnects a handler for a signal. - -### disconnectAll() - -Disconnects all signal handlers for an object. - -### emit(name, ...args) - -Parameters: -* name (`String`) — A signal name -* args (`Any`) — Any number of arguments, of any type - -Emits a signal for an object. Emission stops if a signal handler returns `true`. - -Unlike GObject signals, it is not necessary to declare signals or define their -signature. Simply call `emit()` with whatever signal name you wish, with -whatever arguments you wish. - -### signalHandlerIsConnected(id) - -Parameters: -* id (`Number`) — The ID of the handler to be disconnected - -Returns: -* (`Boolean`) — `true` if connected, or `false` if not - -Checks if a handler ID is connected. - diff -Nru gjs-1.74.0/doc/System.md gjs-1.72.2/doc/System.md --- gjs-1.74.0/doc/System.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/System.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,262 +0,0 @@ -# System - -The `System` module provides common low-level facilities such as access to -process arguments and `exit()`, as well as a number of useful functions and -properties for debugging. - -Note that the majority of the functions and properties in this module should not -be used in normal operation of a GJS application. - -#### Import - -When using ESModules: - -```js -import System from 'system'; -``` - -When using legacy imports: - -```js -const System = imports.system; -``` - -### System.addressOf(object) - -> See also: [`System.addressOfGObject()`](#system-addressofgobject) - -Type: -* Static - -Parameters: -* object (`Object`) — Any `Object` - -Returns: -* (`String`) — A hexadecimal string (e.g. `0xb4f170f0`) - -Return the memory address of any object as a string. - -This is the address of memory being managed by the JavaScript engine, which may -represent a wrapper around memory elsewhere. - -> Caution, don't use this as a unique identifier! -> -> JavaScript's garbage collector can move objects around in memory, or -> deduplicate identical objects, so this value may change during the execution -> of a program. - -### System.addressOfGObject(gobject) - -> See also: [`System.addressOf()`](#system-addressof) - -Type: -* Static - -Parameters: -* gobject (`GObject.Object`) — Any [`GObject.Object`][gobject]-derived instance - -Returns: -* (`String`) — A hexadecimal string (e.g. `0xb4f170f0`) - -> New in GJS 1.58 (GNOME 3.34) - -Return the memory address of any GObject as a string. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### System.breakpoint() - -> Warning: Using this function in code run outside of GDB will abort the process - -Type: -* Static - -Inserts a breakpoint instruction into the code. - -With `System.breakpoint()` calls in your code, a GJS program can be debugged by -running it in GDB: - -``` -gdb --args gjs script.js -``` - -Once GDB has started, you can start the program with `run`. When the debugger -hits a breakpoint it will pause execution of the process and return to the -prompt. You can then use the standard `backtrace` command to print a C++ stack -trace, or use `call gjs_dumpstack()` to print a JavaScript stack trace: - -``` -(gdb) run -Starting program: /usr/bin/gjs -m script.js -... -Thread 1 "gjs" received signal SIGTRAP, Trace/breakpoint trap. -(gdb) call gjs_dumpstack() -== Stack trace for context 0x5555555b7180 == -#0 555555640548 i file:///path/to/script.js:4 (394b8c3cc060 @ 12) -#1 5555556404c8 i file:///path/to/script.js:7 (394b8c3cc0b0 @ 6) -#2 7fffffffd3a0 b self-hosted:2408 (394b8c3a9650 @ 753) -#3 5555556403e8 i self-hosted:2355 (394b8c3a9600 @ 375) -(gdb) -``` - -To continue executing the program, you can use the `continue` (or `cont`) to -resume the process and debug further. - -Remember that if you run the program outside of GDB, it will abort at the -breakpoint, so make sure to remove any calls to `System.breakpoint()` when -you're done debugging. - -### System.clearDateCaches() - -Type: -* Static - -Clears the timezone cache. - -This is a workaround for SpiderMonkey [Bug #1004706][bug-1004706]. - -[bug-1004706]: https://bugzilla.mozilla.org/show_bug.cgi?id=1004706 - -### System.dumpHeap(path) - -See also: The [`heapgraph`][heapgraph] utility in the GJS repository - -Type: -* Static - -Parameters: -* path (`String`) — Optional file path - -Dump a representation of internal heap memory. If `path` is not given, GJS will -write the contents to `stdout`. - -[heapgraph]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/tools/heapgraph.md - -### System.dumpMemoryInfo(path) - -Type: -* Static - -Parameters: -* path (`String`) — Optional file path - -> New in GJS 1.70 (GNOME 41) - -Dump internal garbage collector statistics. If `path` is not given, GJS will -write the contents to `stdout`. - -Example output: - -```json -{ - "gcBytes": 794624, - "gcMaxBytes": 4294967295, - "mallocBytes": 224459, - "gcIsHighFrequencyMode": true, - "gcNumber": 1, - "majorGCCount": 1, - "minorGCCount": 1, - "sliceCount": 1, - "zone": { - "gcBytes": 323584, - "gcTriggerBytes": 42467328, - "gcAllocTrigger": 36097228.8, - "mallocBytes": 120432, - "mallocTriggerBytes": 59768832, - "gcNumber": 1 - } -} -``` - -### System.exit(code) - -Type: -* Static - -Parameters: -* code (`Number`) — An exit code - -This works the same as C's `exit()` function; exits the program, passing a -certain error code to the shell. The shell expects the error code to be zero if -there was no error, or non-zero (any value you please) to indicate an error. - -This value is used by other tools such as `make`; if `make` calls a program that -returns a non-zero error code, then `make` aborts the build. - -### System.gc() - -Type: -* Static - -Run the garbage collector. - -### System.programArgs - -Type: -* `Array(String)` - -> New in GJS 1.68 (GNOME 40) - -A list of arguments passed to the current process. - -This is effectively an alias for the global `ARGV`, which is misleading in that -it is not equivalent to the platform's `argv`. - -### System.programInvocationName - -Type: -* `String` - -> New in GJS 1.68 (GNOME 40) - -This property contains the name of the script as it was invoked from the command -line. - -In C and other languages, this information is contained in the first element of -the platform's equivalent of `argv`, but GJS's `ARGV` only contains the -subsequent command-line arguments. In other words, `ARGV[0]` in GJS is the same -as `argv[1]` in C. - -For example, passing ARGV to a `Gio.Application`/`Gtk.Application` (See also: -[examples/gtk-application.js][example-application]): - -```js -import Gtk from 'gi://Gtk?version=3.0'; -import System from 'system'; - -const myApp = new Gtk.Application(); -myApp.connect("activate", () => log("activated")); -myApp.run([System.programInvocationName, ...ARGV]); -``` - -[example-application]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/examples/gtk-application.js - -### System.programPath - -Type: -* `String` - -> New in GJS 1.68 (GNOME 40) - -The full path of the executed program. - -### System.refcount(gobject) - -Type: -* Static - -Parameters: -* gobject (`GObject.Object`) — A [`GObject.Object`][gobject] - -Return the reference count of any GObject-derived type. When an object's -reference count is zero, it is cleaned up and erased from memory. - -[gobject]: https://gjs-docs.gnome.org/gobject20/gobject.object - -### System.version - -Type: -* `String` - -This property contains version information about GJS. - diff -Nru gjs-1.74.0/doc/Testing.md gjs-1.72.2/doc/Testing.md --- gjs-1.74.0/doc/Testing.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Testing.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -# Testing - -Testing infrastructure for GJS code is unfortunately not as complete as other -languages, and help in the area would be a greatly appreciated contribution to -the community. - -## Jasmine GJS - -[Jasmine GJS][jasmine-gjs] is a fork of the Jasmine testing framework, adapted -for GJS and the GLib event loop. See the [Jasmine Documentation][jasmine-doc] -and the [GJS test suite][gjs-tests] for examples. - -[jasmine-doc]: https://jasmine.github.io/pages/docs_home.html -[jasmine-gjs]: https://github.com/ptomato/jasmine-gjs -[gjs-tests]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/installed-tests/js - -## jsUnit - -> Deprecated: Use [Jasmine GJS](#jasmine-gjs) instead - -The `jsUnit` module was originally used as the testing framework in GJS. It has -long been deprecated in favour of Jasmine. - diff -Nru gjs-1.74.0/doc/Timers.md gjs-1.72.2/doc/Timers.md --- gjs-1.74.0/doc/Timers.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/doc/Timers.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -# Timers - -GJS implements the [WHATWG Timers][whatwg-timers] specification, with some -changes to accommodate the GLib event loop. - -In particular, the returned value of `setInterval()` and `setTimeout()` is not a -`Number`, but a [`GLib.Source`][gsource]. - -#### Import - -The functions in this module are available globally, without import. - -[whatwg-timers]: https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers -[gsource]: https://gjs-docs.gnome.org/glib20/glib.source - -### setInterval(handler, timeout, ...arguments) - -Type: -* Static - -Parameters: -* handler (`Function`) — The callback to invoke -* timeout (`Number`) — Optional interval in milliseconds -* arguments (`Array(Any)`) — Optional arguments to pass to `handler` - -Returns: -* (`GLib.Source`) — The identifier of the repeated action - -> New in GJS 1.72 (GNOME 42) - -Schedules a timeout to run `handler` every `timeout` milliseconds. Any -`arguments` are passed straight through to the `handler`. - -### clearInterval(id) - -Type: -* Static - -Parameters: -* id (`GLib.Source`) — The identifier of the interval you want to cancel. - -> New in GJS 1.72 (GNOME 42) - -Cancels the timeout set with `setInterval()` or `setTimeout()` identified by -`id`. - -### setTimeout(handler, timeout, ...arguments) - -Type: -* Static - -Parameters: -* handler (`Function`) — The callback to invoke -* timeout (`Number`) — Optional timeout in milliseconds -* arguments (`Array(Any)`) — Optional arguments to pass to `handler` - -Returns: -* (`GLib.Source`) — The identifier of the repeated action - -> New in GJS 1.72 (GNOME 42) - -Schedules a timeout to run `handler` after `timeout` milliseconds. Any -`arguments` are passed straight through to the `handler`. - -### clearTimeout(id) - -Type: -* Static - -Parameters: -* id (`GLib.Source`) — The identifier of the timeout you want to cancel. - -> New in GJS 1.72 (GNOME 42) - -Cancels the timeout set with `setTimeout()` or `setInterval()` identified by -`id`. - diff -Nru gjs-1.74.0/examples/calc.js gjs-1.72.2/examples/calc.js --- gjs-1.74.0/examples/calc.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/calc.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,11 +1,13 @@ +#!/usr/bin/env gjs // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2008 Robert Carr -import Gtk from 'gi://Gtk?version=3.0'; +imports.gi.versions.Gtk = '3.0'; +const {Gtk} = imports.gi; Gtk.init(null); -let calcVal = ''; +var calcVal = ''; function updateDisplay() { label.set_markup(`${calcVal}`); @@ -58,7 +60,7 @@ } function packButtons(buttons, vbox) { - let hbox = new Gtk.HBox(); + var hbox = new Gtk.HBox(); hbox.homogeneous = true; @@ -69,13 +71,13 @@ } function createButton(str, func) { - let btn = new Gtk.Button({label: str}); + var btn = new Gtk.Button({label: str}); btn.connect('clicked', func); return btn; } function createButtons() { - let vbox = new Gtk.VBox({homogeneous: true}); + var vbox = new Gtk.VBox({homogeneous: true}); packButtons([ createButton('(', pressedNumber), @@ -120,7 +122,7 @@ return vbox; } -let win = new Gtk.Window({ +var win = new Gtk.Window({ title: 'Calculator', resizable: false, opacity: 0.6, @@ -129,11 +131,11 @@ win.resize(250, 250); win.connect('destroy', () => Gtk.main_quit()); -let label = new Gtk.Label({label: ''}); +var label = new Gtk.Label({label: ''}); label.set_alignment(1, 0); updateDisplay(); -let mainvbox = new Gtk.VBox(); +var mainvbox = new Gtk.VBox(); mainvbox.pack_start(label, false, true, 1); mainvbox.pack_start(new Gtk.HSeparator(), false, true, 5); mainvbox.pack_start(createButtons(), true, true, 2); diff -Nru gjs-1.74.0/examples/dbus-client.js gjs-1.72.2/examples/dbus-client.js --- gjs-1.74.0/examples/dbus-client.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/dbus-client.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2020 Andy Holmes -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; +'use strict'; + +const GLib = imports.gi.GLib; +const Gio = imports.gi.Gio; + /* * An XML DBus Interface @@ -48,8 +51,8 @@ 'org.gnome.gjs.Test', '/org/gnome/gjs/Test' ); - } catch (err) { - logError(err); + } catch (e) { + logError(e); return; } @@ -86,8 +89,8 @@ let value = proxy.SimpleMethodSync(); print(`SimpleMethod: ${value}`); - } catch (err) { - logError(`SimpleMethod: ${err.message}`); + } catch (e) { + logError(`SimpleMethod: ${e.message}`); } proxy.ComplexMethodRemote('input string', (value, error, fdList) => { diff -Nru gjs-1.74.0/examples/dbus-service.js gjs-1.72.2/examples/dbus-service.js --- gjs-1.74.0/examples/dbus-service.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/dbus-service.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2020 Andy Holmes -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; +'use strict'; + +const GLib = imports.gi.GLib; +const Gio = imports.gi.Gio; + /* * An XML DBus Interface diff -Nru gjs-1.74.0/examples/.eslintrc.yml gjs-1.72.2/examples/.eslintrc.yml --- gjs-1.74.0/examples/.eslintrc.yml 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/.eslintrc.yml 2022-08-08 05:05:12.000000000 +0000 @@ -1,6 +1,4 @@ --- -parserOptions: - sourceType: 'module' # SPDX-License-Identifier: MIT OR LGPL-2.0-or-later # SPDX-FileCopyrightText: 2020 Evan Welsh rules: diff -Nru gjs-1.74.0/examples/gettext.js gjs-1.72.2/examples/gettext.js --- gjs-1.74.0/examples/gettext.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gettext.js 2022-08-08 05:05:12.000000000 +0000 @@ -3,27 +3,21 @@ /* * Make sure you have a non english locale installed, for example fr_FR and run - * LANGUAGE=fr_FR gjs -m gettext.js + * LANGUAGE=fr_FR gjs gettext.js * the label should show a translation of 'Print help' */ -import Gettext, {gettext as _} from 'gettext'; -import Gtk from 'gi://Gtk?version=4.0'; -import GLib from 'gi://GLib'; - -Gtk.init(); - -let loop = GLib.MainLoop.new(null, false); +imports.gi.versions.Gtk = '3.0'; +const Gettext = imports.gettext; +const Gtk = imports.gi.Gtk; Gettext.bindtextdomain('gnome-shell', '/usr/share/locale'); Gettext.textdomain('gnome-shell'); -let window = new Gtk.Window({title: 'gettext'}); -window.set_child(new Gtk.Label({label: _('Print help')})); -window.connect('close-request', () => { - loop.quit(); -}); +Gtk.init(null); -window.present(); +let w = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); +w.add(new Gtk.Label({label: Gettext.gettext('Print help')})); +w.show_all(); -loop.run(); +Gtk.main(); diff -Nru gjs-1.74.0/examples/gio-cat.js gjs-1.72.2/examples/gio-cat.js --- gjs-1.74.0/examples/gio-cat.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gio-cat.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2010 litl, LLC -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; +const ByteArray = imports.byteArray; +const GLib = imports.gi.GLib; +const Gio = imports.gi.Gio; let loop = GLib.MainLoop.new(null, false); -const decoder = new TextDecoder(); function cat(filename) { let f = Gio.file_new_for_path(filename); @@ -13,12 +13,12 @@ let contents; try { contents = obj.load_contents_finish(res)[1]; - } catch (err) { - logError(err); + } catch (e) { + logError(e); loop.quit(); return; } - print(decoder.decode(contents)); + print(ByteArray.toString(contents)); loop.quit(); }); diff -Nru gjs-1.74.0/examples/glistmodel.js gjs-1.72.2/examples/glistmodel.js --- gjs-1.74.0/examples/glistmodel.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/glistmodel.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,14 +1,19 @@ +/* exported GjsListStore */ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2020 Andy Holmes -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; +'use strict'; + +const GObject = imports.gi.GObject; +const Gio = imports.gi.Gio; + + /** * An example of implementing the GListModel interface in GJS. The only real * requirement here is that the class be derived from some GObject. */ -export let GjsListStore = GObject.registerClass({ +var GjsListStore = GObject.registerClass({ GTypeName: 'GjsListStore', Implements: [Gio.ListModel], }, class MyList extends GObject.Object { diff -Nru gjs-1.74.0/examples/gtk3.js gjs-1.72.2/examples/gtk3.js --- gjs-1.74.0/examples/gtk3.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gtk3.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later -// SPDX-FileCopyrightText: 2008 litl, LLC - -// Include the version in case both GTK3 and GTK4 installed -// otherwise an exception will be thrown -import Gtk from 'gi://Gtk?version=3.0'; - -// Initialize Gtk before you start calling anything from the import -Gtk.init(null); - -// Construct a top-level window -let win = new Gtk.Window({ - type: Gtk.WindowType.TOPLEVEL, - title: 'A default title', - default_width: 300, - default_height: 250, - // A decent example of how constants are mapped: - // 'Gtk' and 'WindowPosition' from the enum name GtkWindowPosition, - // 'CENTER' from the enum's constant GTK_WIN_POS_CENTER - window_position: Gtk.WindowPosition.CENTER, -}); - -// Object properties can also be set or changed after construction, unless they -// are marked construct-only. -win.title = 'Hello World!'; - -// This is a callback function -function onDeleteEvent() { - log('delete-event emitted'); - // If you return false in the "delete_event" signal handler, Gtk will emit - // the "destroy" signal. - // - // Returning true gives you a chance to pop up 'are you sure you want to - // quit?' type dialogs. - return false; -} - -// When the window is given the "delete_event" signal (this is given by the -// window manager, usually by the "close" option, or on the titlebar), we ask -// it to call the onDeleteEvent() function as defined above. -win.connect('delete-event', onDeleteEvent); - -// GJS will warn when calling a C function with unexpected arguments... -// -// window.connect("destroy", Gtk.main_quit); -// -// ...so use arrow functions for inline callbacks with arguments to adjust -win.connect('destroy', () => { - Gtk.main_quit(); -}); - -// Create a button to close the window -let button = new Gtk.Button({ - label: 'Close the Window', - // Set visible to 'true' if you don't want to call button.show() later - visible: true, - // Another example of constant mapping: - // 'Gtk' and 'Align' are taken from the GtkAlign enum, - // 'CENTER' from the constant GTK_ALIGN_CENTER - valign: Gtk.Align.CENTER, - halign: Gtk.Align.CENTER, -}); - -// Connect to the 'clicked' signal, using another way to call an arrow function -button.connect('clicked', () => win.destroy()); - -// Add the button to the window -win.add(button); - -// Show the window -win.show(); - -// All gtk applications must have a Gtk.main(). Control will end here and wait -// for an event to occur (like a key press or mouse event). The main loop will -// run until Gtk.main_quit is called. -Gtk.main(); - diff -Nru gjs-1.74.0/examples/gtk3-template.js gjs-1.72.2/examples/gtk3-template.js --- gjs-1.74.0/examples/gtk3-template.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gtk3-template.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,12 +1,13 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2021 Andy Holmes -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk?version=3.0'; +imports.gi.versions.Gtk = '3.0'; +const {GObject, Gio, Gtk} = imports.gi; + Gtk.init(null); + /* In this example the template contents are loaded from the file as a string. * * The `Template` property of the class definition will accept: diff -Nru gjs-1.74.0/examples/gtk4-frame-clock.js gjs-1.72.2/examples/gtk4-frame-clock.js --- gjs-1.74.0/examples/gtk4-frame-clock.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gtk4-frame-clock.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later -// SPDX-FileCopyrightText: 2022 Andy Holmes - - -import Gtk from 'gi://Gtk?version=4.0'; -import GLib from 'gi://GLib'; - - -function easeInOutQuad(p) { - if ((p *= 2.0) < 1.0) - return 0.5 * p * p; - - return -0.5 * (--p * (p - 2) - 1); -} - -// When the button is clicked, we'll add a tick callback to run the animation -function _onButtonClicked(widget) { - // Prevent concurrent animations from being triggered - if (widget._animationId) - return; - - const duration = 1000; // one second in milliseconds - let start = Date.now(); - let fadeIn = false; - - // Tick callbacks are just like GSource callbacks. You will get a ID that - // can be passed to Gtk.Widget.remove_tick_callback(), or you can return - // GLib.SOURCE_CONTINUE and GLib.SOURCE_REMOVE as appropriate. - widget._animationId = widget.add_tick_callback(() => { - let now = Date.now(); - - // We've now passed the time duration - if (now >= start + duration) { - // If we just finished fading in, we're all done - if (fadeIn) { - widget._animationId = null; - return GLib.SOURCE_REMOVE; - } - - // If we just finished fading out, we'll start fading in - fadeIn = true; - start = now; - } - - // Apply the easing function to the current progress - let progress = (now - start) / duration; - progress = easeInOutQuad(progress); - - // We are using the progress as the opacity value of the button - widget.opacity = fadeIn ? progress : 1.0 - progress; - - return GLib.SOURCE_CONTINUE; - }); -} - - -// Initialize GTK -Gtk.init(); -const loop = GLib.MainLoop.new(null, false); - -// Create a button to start the animation -const button = new Gtk.Button({ - label: 'Fade out, fade in', - valign: Gtk.Align.CENTER, - halign: Gtk.Align.CENTER, -}); -button.connect('clicked', _onButtonClicked); - -// Create a top-level window -const win = new Gtk.Window({ - title: 'GTK4 Frame Clock', - default_width: 300, - default_height: 250, - child: button, -}); - -// When a widget is destroyed any tick callbacks will be removed automatically, -// so in practice our callback would be cleaned up when the window closes. -win.connect('close-request', () => { - // Note that removing a tick callback by ID will interrupt its progress, so - // we are resetting the button opacity manually after it's removed. - if (button._animationId) { - button.remove_tick_callback(button._animationId); - button.opacity = 1.0; - } - - loop.quit(); -}); - -// Show the window -win.present(); -loop.run(); - diff -Nru gjs-1.74.0/examples/gtk4.js gjs-1.72.2/examples/gtk4.js --- gjs-1.74.0/examples/gtk4.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gtk4.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later -// SPDX-FileCopyrightText: 2008 litl, LLC - -// Include the version in case both GTK3 and GTK4 installed -// otherwise an exception will be thrown -import Gtk from 'gi://Gtk?version=4.0'; -import GLib from 'gi://GLib'; - -// Initialize Gtk before you start calling anything from the import -Gtk.init(); - -// If you are not using GtkApplication which has its own mainloop -// you must create it yourself, see gtk-application.js example -let loop = GLib.MainLoop.new(null, false); - -// Construct a window -let win = new Gtk.Window({ - title: 'A default title', - default_width: 300, - default_height: 250, -}); - -// Object properties can also be set or changed after construction, unless they -// are marked construct-only. -win.title = 'Hello World!'; - -// This is a callback function -function onCloseRequest() { - log('close-request emitted'); - loop.quit(); -} - -// When the window is given the "close-request" signal (this is given by the -// window manager, usually by the "close" option, or on the titlebar), we ask -// it to call the onCloseRequest() function as defined above. -win.connect('close-request', onCloseRequest); - -// Create a button to close the window -let button = new Gtk.Button({ - label: 'Close the Window', - // An example of how constants are mapped: - // 'Gtk' and 'Align' are taken from the GtkAlign enum, - // 'CENTER' from the constant GTK_ALIGN_CENTER - valign: Gtk.Align.CENTER, - halign: Gtk.Align.CENTER, -}); - -// Connect to the 'clicked' signal, using another way to call an arrow function -button.connect('clicked', () => win.close()); - -// Add the button to the window -win.set_child(button); - -// Show the window -win.present(); - -// Control will end here and wait for an event to occur -// (like a key press or mouse event) -// The main loop will run until loop.quit is called. -loop.run(); - -log('The main loop has completed.'); diff -Nru gjs-1.74.0/examples/gtk4-template.js gjs-1.72.2/examples/gtk4-template.js --- gjs-1.74.0/examples/gtk4-template.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gtk4-template.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,10 +1,9 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2021 Andy Holmes -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk?version=4.0'; +imports.gi.versions.Gtk = '4.0'; +const {GLib, GObject, Gio, Gtk} = imports.gi; + Gtk.init(); diff -Nru gjs-1.74.0/examples/gtk-application.js gjs-1.72.2/examples/gtk-application.js --- gjs-1.74.0/examples/gtk-application.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/gtk-application.js 2022-08-08 05:05:12.000000000 +0000 @@ -2,17 +2,21 @@ // SPDX-FileCopyrightText: 2017 Andy Holmes // See the note about Application.run() at the bottom of the script -import System from 'system'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -// Include the version in case both GTK3 and GTK4 installed -// otherwise an exception will be thrown -import Gtk from 'gi://Gtk?version=4.0'; +const System = imports.system; + +// Include this in case both GTK3 and GTK4 installed, otherwise an exception +// will be thrown +imports.gi.versions.Gtk = '3.0'; + +const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; +const GObject = imports.gi.GObject; +const Gtk = imports.gi.Gtk; + // An example GtkApplication with a few bells and whistles, see also: // https://wiki.gnome.org/HowDoI/GtkApplication -let ExampleApplication = GObject.registerClass({ +var ExampleApplication = GObject.registerClass({ Properties: { 'exampleprop': GObject.ParamSpec.string( 'exampleprop', // property name @@ -69,13 +73,13 @@ }); let label = new Gtk.Label({label: this.exampleprop}); - window.set_child(label); + window.add(label); - window.connect('close-request', () => { + window.connect('delete-event', () => { this.quit(); }); - window.present(); + window.show_all(); // Example GNotification, see: https://developer.gnome.org/GNotification/ let notif = new Gio.Notification(); diff -Nru gjs-1.74.0/examples/gtk.js gjs-1.72.2/examples/gtk.js --- gjs-1.74.0/examples/gtk.js 1970-01-01 00:00:00.000000000 +0000 +++ gjs-1.72.2/examples/gtk.js 2022-08-08 05:05:12.000000000 +0000 @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later +// SPDX-FileCopyrightText: 2008 litl, LLC + +// Include this in case both GTK3 and GTK4 installed, otherwise an exception +// will be thrown +imports.gi.versions.Gtk = '3.0'; +const Gtk = imports.gi.Gtk; + +// Initialize Gtk before you start calling anything from the import +Gtk.init(null); + +// Construct a top-level window +let win = new Gtk.Window({ + type: Gtk.WindowType.TOPLEVEL, + title: 'A default title', + default_width: 300, + default_height: 250, + // A decent example of how constants are mapped: + // 'Gtk' and 'WindowPosition' from the enum name GtkWindowPosition, + // 'CENTER' from the enum's constant GTK_WIN_POS_CENTER + window_position: Gtk.WindowPosition.CENTER, +}); + +// Object properties can also be set or changed after construction, unless they +// are marked construct-only. +win.title = 'Hello World!'; + +// This is a callback function +function onDeleteEvent() { + log('delete-event emitted'); + // If you return false in the "delete_event" signal handler, Gtk will emit + // the "destroy" signal. + // + // Returning true gives you a chance to pop up 'are you sure you want to + // quit?' type dialogs. + return false; +} + +// When the window is given the "delete_event" signal (this is given by the +// window manager, usually by the "close" option, or on the titlebar), we ask +// it to call the onDeleteEvent() function as defined above. +win.connect('delete-event', onDeleteEvent); + +// GJS will warn when calling a C function with unexpected arguments... +// +// window.connect("destroy", Gtk.main_quit); +// +// ...so use arrow functions for inline callbacks with arguments to adjust +win.connect('destroy', () => { + Gtk.main_quit(); +}); + +// Create a button to close the window +let button = new Gtk.Button({ + label: 'Close the Window', + // Set visible to 'true' if you don't want to call button.show() later + visible: true, + // Another example of constant mapping: + // 'Gtk' and 'Align' are taken from the GtkAlign enum, + // 'CENTER' from the constant GTK_ALIGN_CENTER + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, +}); + +// Connect to the 'clicked' signal, using another way to call an arrow function +button.connect('clicked', () => win.destroy()); + +// Add the button to the window +win.add(button); + +// Show the window +win.show(); + +// All gtk applications must have a Gtk.main(). Control will end here and wait +// for an event to occur (like a key press or mouse event). The main loop will +// run until Gtk.main_quit is called. +Gtk.main(); + diff -Nru gjs-1.74.0/examples/http-client.js gjs-1.72.2/examples/http-client.js --- gjs-1.74.0/examples/http-client.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/http-client.js 2022-08-08 05:05:12.000000000 +0000 @@ -4,34 +4,32 @@ // This is a simple example of a HTTP client in Gjs using libsoup // https://developer.gnome.org/libsoup/stable/libsoup-client-howto.html -import Soup from 'gi://Soup?version=3.0'; -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; +const Soup = imports.gi.Soup; +const GLib = imports.gi.GLib; +const byteArray = imports.byteArray; const loop = GLib.MainLoop.new(null, false); const session = new Soup.Session(); const message = new Soup.Message({ method: 'GET', - uri: GLib.Uri.parse('http://localhost:1080/hello?myname=gjs', GLib.UriFlags.NONE), + uri: Soup.URI.new('http://localhost:1080/hello?myname=gjs'), }); -const decoder = new TextDecoder(); -session.send_async(message, null, null, send_async_callback); +session.send_async(message, null, send_async_callback); -function splice_callback(outputStream, result) { +function read_bytes_async_callback(inputStream, res) { let data; try { - outputStream.splice_finish(outputStream, result); - data = outputStream.steal_as_bytes(); - } catch (err) { - logError(err); + data = inputStream.read_bytes_finish(res); + } catch (e) { + logError(e); loop.quit(); return; } - console.log('body:', decoder.decode(data.toArray())); + log(`body:\n${byteArray.toString(byteArray.fromGBytes(data))}`); loop.quit(); } @@ -41,24 +39,18 @@ try { inputStream = session.send_finish(res); - } catch (err) { - logError(err); + } catch (e) { + logError(e); loop.quit(); return; } - console.log('status:', message.status_code, message.reason_phrase); - - const response_headers = message.get_response_headers(); - response_headers.foreach((name, value) => { - console.log(name, ':', value); + log(`status: ${message.status_code} - ${message.reason_phrase}`); + message.response_headers.foreach((name, value) => { + log(`${name}: ${value}`); }); - const contentType_ = response_headers.get_one('content-type'); - const outputStream = Gio.MemoryOutputStream.new_resizable(); - outputStream.splice_async(inputStream, - Gio.OutputStreamSpliceFlags.CLOSE_TARGET, - GLib.PRIORITY_DEFAULT, null, splice_callback); + inputStream.read_bytes_async(message.response_headers.get('content-length'), null, null, read_bytes_async_callback); } loop.run(); diff -Nru gjs-1.74.0/examples/http-server.js gjs-1.72.2/examples/http-server.js --- gjs-1.74.0/examples/http-server.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/http-server.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,21 +1,17 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2010 litl, LLC -// This is a simple example of a HTTP server in GJS using libsoup -// open http://localhost:1080 in your browser or use http-client.js +// This is a simple example of a HTTP server in Gjs using libsoup -import Soup from 'gi://Soup?version=3.0'; -import GLib from 'gi://GLib'; +const Soup = imports.gi.Soup; -const loop = GLib.MainLoop.new(null, false); - -function handler(_server, msg, _path, _query) { - msg.set_status(200, null); - msg.get_response_headers().set_content_type('text/html', {charset: 'UTF-8'}); - msg.get_response_body().append(` +function handler(server, msg, path, query, client) { + msg.status_code = 200; + msg.response_headers.set_content_type('text/html', {}); + msg.response_body.append(` - Greetings, visitor from ${msg.get_remote_host()}
+ Greetings, visitor from ${client.get_host()}
What is your name?
@@ -25,15 +21,15 @@ `); } -function helloHandler(_server, msg, path, query) { +function helloHandler(server, msg, path, query) { if (!query) { msg.set_redirect(302, '/'); return; } - msg.set_status(200, null); - msg.get_response_headers().set_content_type('text/html', {charset: 'UTF-8'}); - msg.get_response_body().append(` + msg.status_code = 200; + msg.response_headers.set_content_type('text/html', {charset: 'UTF-8'}); + msg.response_body.append(` Hello, ${query.myname}! ☺
@@ -44,12 +40,10 @@ } function main() { - let server = new Soup.Server(); + let server = new Soup.Server({port: 1080}); server.add_handler('/', handler); server.add_handler('/hello', helloHandler); - server.listen_local(1080, Soup.ServerListenOptions.IPV4_ONLY); + server.run(); } main(); - -loop.run(); diff -Nru gjs-1.74.0/examples/README gjs-1.72.2/examples/README --- gjs-1.74.0/examples/README 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/README 2022-08-08 05:05:12.000000000 +0000 @@ -1,5 +1,3 @@ In order to run those example scripts, do: -```sh -gjs -m script-filename.js -``` + gjs-console script-filename.js diff -Nru gjs-1.74.0/examples/timers.js gjs-1.72.2/examples/timers.js --- gjs-1.74.0/examples/timers.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/timers.js 2022-08-08 05:05:12.000000000 +0000 @@ -2,11 +2,7 @@ // SPDX-FileCopyrightText: 2021 Evan Welsh // This example demonstrates that Promises always execute prior -// to timeouts. It should log "hello" then "world". - -import GLib from 'gi://GLib'; - -const loop = GLib.MainLoop.new(null, false); +// to timeouts. It should log "java" then "script". const promise = new Promise(r => { let i = 100; @@ -17,11 +13,9 @@ }); setTimeout(() => { - promise.then(() => log('hello')); + promise.then(() => log('java')); }); setTimeout(() => { - log('world'); + log('script'); }); - -loop.run(); diff -Nru gjs-1.74.0/examples/webkit.js gjs-1.72.2/examples/webkit.js --- gjs-1.74.0/examples/webkit.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/webkit.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,15 +1,17 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2008 litl, LLC -import Gtk from 'gi://Gtk?version=3.0'; -import WebKit from 'gi://WebKit2?version=4.0'; +imports.gi.versions.Gtk = '3.0'; +imports.gi.versions.WebKit2 = '4.0'; +const Gtk = imports.gi.Gtk; +const WebKit = imports.gi.WebKit2; Gtk.init(null); let win = new Gtk.Window(); let view = new WebKit.WebView(); -view.load_uri('https://www.gnome.org'); +view.load_uri('http://www.google.com/'); win.add(view); win.connect('destroy', () => { diff -Nru gjs-1.74.0/examples/websocket-client.js gjs-1.72.2/examples/websocket-client.js --- gjs-1.74.0/examples/websocket-client.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/examples/websocket-client.js 2022-08-08 05:05:12.000000000 +0000 @@ -4,27 +4,27 @@ // This is an example of a WebSocket client in Gjs using libsoup // https://developer.gnome.org/libsoup/stable/libsoup-2.4-WebSockets.html -import Soup from 'gi://Soup?version=3.0'; -import GLib from 'gi://GLib'; +const Soup = imports.gi.Soup; +const GLib = imports.gi.GLib; +const byteArray = imports.byteArray; const loop = GLib.MainLoop.new(null, false); const session = new Soup.Session(); const message = new Soup.Message({ method: 'GET', - uri: GLib.Uri.parse('wss://ws.postman-echo.com/raw', GLib.UriFlags.NONE), + uri: Soup.URI.new('wss://echo.websocket.org'), }); -const decoder = new TextDecoder(); -session.websocket_connect_async(message, null, [], null, null, websocket_connect_async_callback); +session.websocket_connect_async(message, 'origin', [], null, websocket_connect_async_callback); function websocket_connect_async_callback(_session, res) { let connection; try { connection = session.websocket_connect_finish(res); - } catch (err) { - logError(err); + } catch (e) { + logError(e); loop.quit(); return; } @@ -43,7 +43,7 @@ if (type !== Soup.WebsocketDataType.TEXT) return; - const str = decoder.decode(data.toArray()); + const str = byteArray.toString(byteArray.fromGBytes(data)); log(`message: ${str}`); connection.close(Soup.WebsocketCloseCode.NORMAL, null); }); diff -Nru gjs-1.74.0/gi/arg-cache.cpp gjs-1.72.2/gi/arg-cache.cpp --- gjs-1.74.0/gi/arg-cache.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/arg-cache.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -6,7 +6,6 @@ #include #include -#include // for size_t #include #include @@ -26,7 +25,7 @@ #include // for UniqueChars #include #include -#include // for InformalValueTypeName, JS_TypeOfValue +#include // for JS_TypeOfValue #include // for JS_GetObjectFunction #include // for JSTYPE_FUNCTION @@ -48,9 +47,7 @@ #include "gi/value.h" #include "gi/wrapperutils.h" // for GjsTypecheckNoThrow #include "gjs/byteArray.h" -#include "gjs/enum-utils.h" // for operator&, operator|=, operator| #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "util/log.h" enum ExpectedType { @@ -64,9 +61,34 @@ static_assert(G_N_ELEMENTS(expected_type_names) == ExpectedType::LAST, "Names must match the values in ExpectedType"); -static constexpr void gjs_g_argument_set_array_length(GITypeTag tag, - GIArgument* arg, - size_t value) { +// A helper function to retrieve array lengths from a GIArgument (letting the +// compiler generate good instructions in case of big endian machines) +[[nodiscard]] size_t gjs_g_argument_get_array_length(GITypeTag tag, + GIArgument* arg) { + switch (tag) { + case GI_TYPE_TAG_INT8: + return gjs_arg_get(arg); + case GI_TYPE_TAG_UINT8: + return gjs_arg_get(arg); + case GI_TYPE_TAG_INT16: + return gjs_arg_get(arg); + case GI_TYPE_TAG_UINT16: + return gjs_arg_get(arg); + case GI_TYPE_TAG_INT32: + return gjs_arg_get(arg); + case GI_TYPE_TAG_UINT32: + return gjs_arg_get(arg); + case GI_TYPE_TAG_INT64: + return gjs_arg_get(arg); + case GI_TYPE_TAG_UINT64: + return gjs_arg_get(arg); + default: + g_assert_not_reached(); + } +} + +static void gjs_g_argument_set_array_length(GITypeTag tag, GIArgument* arg, + size_t value) { switch (tag) { case GI_TYPE_TAG_INT8: gjs_arg_set(arg, value); @@ -144,10 +166,7 @@ }; struct TypeInfo { - constexpr GITypeInfo* type_info() const { - // Should be const GITypeInfo*, but G-I APIs won't accept that - return const_cast(&m_type_info); - } + constexpr const GITypeInfo* type_info() const { return &m_type_info; } GITypeInfo m_type_info; }; @@ -186,8 +205,7 @@ m_arg_pos = pos; } - constexpr bool set_out_parameter(GjsFunctionCallState* state, - GIArgument* arg) { + bool set_out_parameter(GjsFunctionCallState* state, GIArgument* arg) { gjs_arg_unset(&state->out_cvalue(m_arg_pos)); gjs_arg_set(arg, &gjs_arg_member(&state->out_cvalue(m_arg_pos))); return true; @@ -693,8 +711,6 @@ bool release(JSContext*, GjsFunctionCallState*, GIArgument*, GIArgument*) override; - private: - ffi_closure *m_ffi_closure; }; using CArrayIn = ExplicitArrayIn; @@ -717,44 +733,26 @@ GJS_JSAPI_RETURN_CONVENTION bool NotIntrospectable::in(JSContext* cx, GjsFunctionCallState* state, GIArgument*, JS::HandleValue) { - const char* reason_string = "invalid introspection"; - - switch (m_reason) { - case CALLBACK_OUT: - reason_string = "callback out-argument"; - break; - case DESTROY_NOTIFY_NO_CALLBACK: - reason_string = "DestroyNotify argument with no callback"; - break; - case DESTROY_NOTIFY_NO_USER_DATA: - reason_string = "DestroyNotify argument with no user data"; - break; - case INTERFACE_TRANSFER_CONTAINER: - reason_string = "type not supported for (transfer container)"; - break; - case OUT_CALLER_ALLOCATES_NON_STRUCT: - reason_string = "type not supported for (out caller-allocates)"; - break; - case UNREGISTERED_BOXED_WITH_TRANSFER: - reason_string = - "boxed type with transfer not registered as a GType"; - break; - case UNREGISTERED_UNION: - reason_string = "union type not registered as a GType"; - break; - case UNSUPPORTED_TYPE: - reason_string = "type not supported by introspection"; - break; - case LAST_REASON: - g_assert_not_reached(); - } + static const char* reason_strings[] = { + "callback out-argument", + "DestroyNotify argument with no callback", + "DestroyNotify argument with no user data", + "type not supported for (transfer container)", + "type not supported for (out caller-allocates)", + "boxed type with transfer not registered as a GType", + "union type not registered as a GType", + "type not supported by introspection", + }; + static_assert( + G_N_ELEMENTS(reason_strings) == NotIntrospectableReason::LAST_REASON, + "Explanations must match the values in NotIntrospectableReason"); gjs_throw(cx, "Function %s() cannot be called: argument '%s' with type %s is " "not introspectable because it has a %s", state->display_name().get(), m_arg_name, g_type_tag_to_string(g_type_info_get_tag(&m_type_info)), - reason_string); + reason_strings[m_reason]); return false; } @@ -831,12 +829,11 @@ bool CallbackIn::in(JSContext* cx, GjsFunctionCallState* state, GIArgument* arg, JS::HandleValue value) { GjsCallbackTrampoline* trampoline; - void* closure; + ffi_closure* closure; if (value.isNull() && m_nullable) { closure = nullptr; trampoline = nullptr; - m_ffi_closure = nullptr; } else { if (JS_TypeOfValue(cx, value) != JSTYPE_FUNCTION) { gjs_throw(cx, "Expected function for callback argument %s, got %s", @@ -861,7 +858,6 @@ return false; } closure = trampoline->closure(); - m_ffi_closure = trampoline->get_ffi_closure(); } if (has_callback_destroy()) { @@ -886,11 +882,10 @@ } bool keep_forever = - !has_callback_destroy() && ( #if GI_CHECK_VERSION(1, 72, 0) - m_scope == GI_SCOPE_TYPE_FOREVER || + m_scope == GI_SCOPE_TYPE_FOREVER || #endif - m_scope == GI_SCOPE_TYPE_NOTIFIED); + m_scope == GI_SCOPE_TYPE_NOTIFIED && !has_callback_destroy(); if (trampoline && keep_forever) { trampoline->mark_forever(); @@ -1419,7 +1414,7 @@ GJS_JSAPI_RETURN_CONVENTION bool CallbackIn::release(JSContext*, GjsFunctionCallState*, GIArgument* in_arg, GIArgument* out_arg [[maybe_unused]]) { - ffi_closure *closure = m_ffi_closure; + auto* closure = gjs_arg_get(in_arg); if (!closure) return true; @@ -1508,7 +1503,9 @@ constexpr size_t argument_maximum_size() { if constexpr (std::is_same_v) return 24; - if constexpr (std::is_same_v || + // COMPAT: Work around cppcheck bug, fixed in cppcheck 2.6. + // https://trac.cppcheck.net/ticket/10015 + if constexpr (std::is_same{} || std::is_same_v) return 40; else diff -Nru gjs-1.74.0/gi/arg-cache.h gjs-1.72.2/gi/arg-cache.h --- gjs-1.74.0/gi/arg-cache.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/arg-cache.h 2022-08-08 05:05:12.000000000 +0000 @@ -8,6 +8,7 @@ #include +#include #include #include @@ -230,4 +231,7 @@ } // namespace Gjs +[[nodiscard]] size_t gjs_g_argument_get_array_length(GITypeTag tag, + GIArgument* arg); + #endif // GI_ARG_CACHE_H_ diff -Nru gjs-1.74.0/gi/arg.cpp gjs-1.72.2/gi/arg.cpp --- gjs-1.74.0/gi/arg.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/arg.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -20,7 +20,6 @@ #include // for JS_ReportOutOfMemory #include #include // for RootedVector, MutableWrappedPtrOp... -#include // for JS_GetElement, JS_HasPropertyById #include // for JSPROP_ENUMERATE #include #include @@ -29,7 +28,7 @@ #include #include #include -#include // for InformalValueTypeName, IdVector +#include // for JS_ReportOutOfMemory, JS_GetElement #include // for JS_GetObjectFunction #include "gi/arg-inl.h" @@ -52,7 +51,6 @@ #include "gjs/byteArray.h" #include "gjs/context-private.h" #include "gjs/enum-utils.h" -#include "gjs/macros.h" #include "gjs/jsapi-util.h" #include "util/log.h" #include "util/misc.h" @@ -211,10 +209,6 @@ } } -[[nodiscard]] static inline bool is_string_type(GITypeTag tag) { - return tag == GI_TYPE_TAG_FILENAME || tag == GI_TYPE_TAG_UTF8; -} - /* Check if an argument of the given needs to be released if we obtained it * from out argument (or the return value), and we're transferring ownership */ @@ -346,7 +340,7 @@ /* Don't use key/value destructor functions here, because we can't * construct correct ones in general if the value type is complex. * Rely on the type-aware g_argument_release functions. */ - if (is_string_type(key_type)) + if (key_type == GI_TYPE_TAG_UTF8 || key_type == GI_TYPE_TAG_FILENAME) return g_hash_table_new(g_str_hash, g_str_equal); return g_hash_table_new(NULL, NULL); } @@ -973,11 +967,16 @@ } } -static GArray* garray_new_for_storage_type(unsigned length, - GITypeTag storage_type) { +GJS_JSAPI_RETURN_CONVENTION +static GArray* +gjs_g_array_new_for_type(JSContext *context, + unsigned int length, + GITypeInfo *param_info) +{ guint element_size; + GITypeTag element_type = g_type_info_get_storage_type(param_info); - switch (storage_type) { + switch (element_type) { case GI_TYPE_TAG_BOOLEAN: element_size = sizeof(gboolean); break; @@ -1021,7 +1020,9 @@ break; case GI_TYPE_TAG_VOID: default: - g_assert_not_reached(); + gjs_throw(context, + "Unhandled GArray element-type %d", element_type); + return NULL; } return g_array_sized_new(true, false, element_size, length); @@ -1719,8 +1720,10 @@ if (array_type == GI_ARRAY_TYPE_C) { gjs_arg_set(arg, data.release()); } else if (array_type == GI_ARRAY_TYPE_ARRAY) { - GITypeTag storage_type = g_type_info_get_storage_type(param_info); - GArray* array = garray_new_for_storage_type(length, storage_type); + GArray *array = gjs_g_array_new_for_type(context, length, param_info); + + if (!array) + return false; if (data) g_array_append_vals(array, data, length); diff -Nru gjs-1.74.0/gi/arg-inl.h gjs-1.72.2/gi/arg-inl.h --- gjs-1.74.0/gi/arg-inl.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/arg-inl.h 2022-08-08 05:05:12.000000000 +0000 @@ -39,7 +39,7 @@ // appropriate union member for type T and returns the replaced value. template -[[nodiscard]] constexpr inline decltype(auto) gjs_arg_member(GIArgument* arg) { +[[nodiscard]] inline decltype(auto) gjs_arg_member(GIArgument* arg) { return (arg->*member); } @@ -47,7 +47,7 @@ * which are in fact typedef's of other generic types. * Setting a tag for a type allows to perform proper specialization. */ template -[[nodiscard]] constexpr inline decltype(auto) gjs_arg_member(GIArgument* arg) { +[[nodiscard]] inline decltype(auto) gjs_arg_member(GIArgument* arg) { if constexpr (TAG == GI_TYPE_TAG_VOID) { if constexpr (std::is_same_v) return gjs_arg_member<&GIArgument::v_boolean>(arg); @@ -115,7 +115,7 @@ } template -constexpr inline void gjs_arg_set(GIArgument* arg, T v) { +inline void gjs_arg_set(GIArgument* arg, T v) { if constexpr (std::is_pointer_v) { using NonconstPtrT = std::add_pointer_t>>; @@ -132,18 +132,18 @@ // Store function pointers as void*. It is a requirement of GLib that your // compiler can do this template -constexpr inline void gjs_arg_set(GIArgument* arg, ReturnT (*v)(Args...)) { +inline void gjs_arg_set(GIArgument* arg, ReturnT (*v)(Args...)) { gjs_arg_member(arg) = reinterpret_cast(v); } template -constexpr inline std::enable_if_t> gjs_arg_set( - GIArgument* arg, void* v) { +inline std::enable_if_t> gjs_arg_set(GIArgument* arg, + void *v) { gjs_arg_set(arg, gjs_pointer_to_int(v)); } template -[[nodiscard]] constexpr inline T gjs_arg_get(GIArgument* arg) { +[[nodiscard]] inline T gjs_arg_get(GIArgument* arg) { if constexpr (std::is_same_v || (std::is_same_v && TAG == GI_TYPE_TAG_BOOLEAN)) return T(!!gjs_arg_member(arg)); @@ -152,12 +152,12 @@ } template -[[nodiscard]] constexpr inline void* gjs_arg_get_as_pointer(GIArgument* arg) { +[[nodiscard]] inline void* gjs_arg_get_as_pointer(GIArgument* arg) { return gjs_int_to_pointer(gjs_arg_get(arg)); } template -constexpr inline void gjs_arg_unset(GIArgument* arg) { +inline void gjs_arg_unset(GIArgument* arg) { if constexpr (std::is_pointer_v) gjs_arg_set(arg, nullptr); else @@ -165,7 +165,7 @@ } template -[[nodiscard]] constexpr inline T gjs_arg_steal(GIArgument* arg) { +[[nodiscard]] inline T gjs_arg_steal(GIArgument* arg) { auto val = gjs_arg_get(arg); gjs_arg_unset(arg); return val; @@ -174,10 +174,10 @@ // Implementation to store rounded (u)int64_t numbers into double template -[[nodiscard]] inline constexpr std::enable_if_t< - std::is_integral_v && (std::numeric_limits::max() > - std::numeric_limits::max()), - double> +[[nodiscard]] inline std::enable_if_t && + (std::numeric_limits::max() > + std::numeric_limits::max()), + double> gjs_arg_get_maybe_rounded(GIArgument* arg) { BigT val = gjs_arg_get(arg); @@ -211,29 +211,3 @@ return true; } - -// A helper function to retrieve array lengths from a GIArgument (letting the -// compiler generate good instructions in case of big endian machines) -[[nodiscard]] constexpr size_t gjs_g_argument_get_array_length( - GITypeTag tag, GIArgument* arg) { - switch (tag) { - case GI_TYPE_TAG_INT8: - return gjs_arg_get(arg); - case GI_TYPE_TAG_UINT8: - return gjs_arg_get(arg); - case GI_TYPE_TAG_INT16: - return gjs_arg_get(arg); - case GI_TYPE_TAG_UINT16: - return gjs_arg_get(arg); - case GI_TYPE_TAG_INT32: - return gjs_arg_get(arg); - case GI_TYPE_TAG_UINT32: - return gjs_arg_get(arg); - case GI_TYPE_TAG_INT64: - return gjs_arg_get(arg); - case GI_TYPE_TAG_UINT64: - return gjs_arg_get(arg); - default: - g_assert_not_reached(); - } -} diff -Nru gjs-1.74.0/gi/boxed.cpp gjs-1.72.2/gi/boxed.cpp --- gjs-1.74.0/gi/boxed.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/boxed.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -19,8 +19,6 @@ #include #include // for GCHashMap #include // for MutableWrappedPtrOperations -#include // for SetReservedSlot -#include // for JS_DefineFunction, JS_Enumerate #include #include #include @@ -30,6 +28,7 @@ #include // for IdVector #include +#include "gi/arg-cache.h" #include "gi/arg-inl.h" #include "gi/arg.h" #include "gi/boxed.h" @@ -40,8 +39,6 @@ #include "gjs/atoms.h" #include "gjs/context-private.h" #include "gjs/jsapi-class.h" -#include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "util/log.h" @@ -104,7 +101,7 @@ if (flags & GI_FUNCTION_IS_METHOD) { const char* name = meth_info.name(); jsid id = gjs_intern_string_to_id(cx, name); - if (id.isVoid()) + if (id == JSID_VOID) return false; if (!properties.append(id)) { JS_ReportOutOfMemory(cx); @@ -173,7 +170,8 @@ // We get the string as a jsid later, which is interned. We intern the // string here as well, so it will be the same string pointer - JSString* atom = JS_AtomizeAndPinString(cx, field_info.name()); + JS::RootedString name(cx, JS_NewStringCopyZ(cx, field_info.name())); + JSString* atom = JS_AtomizeAndPinJSString(cx, name); result->putNewInfallible(atom, std::move(field_info)); } @@ -508,8 +506,7 @@ /* We never actually read the reserved slot, but we put the parent object * into it to hold onto the parent object. */ - JS::SetReservedSlot(obj, BoxedInstance::PARENT_OBJECT, - JS::ObjectValue(*parent_obj)); + JS_SetReservedSlot(obj, 0, JS::ObjectValue(*parent_obj)); value.setObject(*obj); return true; @@ -764,6 +761,7 @@ nullptr, // mayResolve &BoxedBase::finalize, nullptr, // call + nullptr, // hasInstance nullptr, // construct &BoxedBase::trace }; @@ -775,7 +773,8 @@ */ const struct JSClass BoxedBase::klass = { "GObject_Boxed", - JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_FOREGROUND_FINALIZE, + JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE | + JSCLASS_HAS_RESERVED_SLOTS(1), &BoxedBase::class_ops }; // clang-format on @@ -929,7 +928,7 @@ : GIWrapperPrototype(info, gtype), m_zero_args_constructor(-1), m_default_constructor(-1), - m_default_constructor_name(JS::PropertyKey::Void()), + m_default_constructor_name(JSID_VOID), m_can_allocate_directly(struct_is_simple(info)) { if (!m_can_allocate_directly) { m_can_allocate_directly_without_pointers = false; @@ -944,8 +943,8 @@ bool BoxedPrototype::init(JSContext* context) { int i, n_methods; int first_constructor = -1; - jsid first_constructor_name = JS::PropertyKey::Void(); - jsid zero_args_constructor_name = JS::PropertyKey::Void(); + jsid first_constructor_name = JSID_VOID; + jsid zero_args_constructor_name = JSID_VOID; if (m_gtype != G_TYPE_NONE) { /* If the structure is registered as a boxed, we can create a new instance by @@ -966,7 +965,7 @@ first_constructor = i; first_constructor_name = gjs_intern_string_to_id(context, func_info.name()); - if (first_constructor_name.isVoid()) + if (first_constructor_name == JSID_VOID) return false; } @@ -975,7 +974,7 @@ m_zero_args_constructor = i; zero_args_constructor_name = gjs_intern_string_to_id(context, func_info.name()); - if (zero_args_constructor_name.isVoid()) + if (zero_args_constructor_name == JSID_VOID) return false; } diff -Nru gjs-1.74.0/gi/boxed.h gjs-1.72.2/gi/boxed.h --- gjs-1.74.0/gi/boxed.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/boxed.h 2022-08-08 05:05:12.000000000 +0000 @@ -7,7 +7,6 @@ #include -#include // for size_t #include #include // for unique_ptr @@ -16,7 +15,6 @@ #include #include -#include #include // for GCHashMap #include // for DefaultHasher #include @@ -35,6 +33,9 @@ namespace JS { class CallArgs; } +namespace js { +class SystemAllocPolicy; +} /* To conserve memory, we have two different kinds of private data for GBoxed * JS wrappers: BoxedInstance, and BoxedPrototype. Both inherit from BoxedBase @@ -159,9 +160,6 @@ friend class GIWrapperBase; friend class BoxedBase; // for field_getter, etc. - // Reserved slots - static const size_t PARENT_OBJECT = 1; - bool m_allocated_directly : 1; bool m_owning_ptr : 1; // if set, the JS wrapper owns the C memory referred // to by m_ptr. diff -Nru gjs-1.74.0/gi/closure.cpp gjs-1.72.2/gi/closure.cpp --- gjs-1.74.0/gi/closure.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/closure.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -8,12 +8,11 @@ #include // for g_assert -#include #include #include #include #include -#include // for JS_GetFunctionObject +#include // for JS_IsExceptionPending, Call, JS_Get... #include "gi/closure.h" #include "gjs/context-private.h" diff -Nru gjs-1.74.0/gi/closure.h gjs-1.72.2/gi/closure.h --- gjs-1.74.0/gi/closure.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/closure.h 2022-08-08 05:05:12.000000000 +0000 @@ -12,6 +12,7 @@ #include #include +#include #include #include "gi/utils-inl.h" diff -Nru gjs-1.74.0/gi/cwrapper.cpp gjs-1.72.2/gi/cwrapper.cpp --- gjs-1.74.0/gi/cwrapper.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/cwrapper.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -9,6 +9,7 @@ #include // for JSPROP_PERMANENT #include #include +#include // for JS_DefinePropertyById #include "gi/cwrapper.h" #include "gi/gtype.h" diff -Nru gjs-1.74.0/gi/cwrapper.h gjs-1.72.2/gi/cwrapper.h --- gjs-1.74.0/gi/cwrapper.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/cwrapper.h 2022-08-08 05:05:12.000000000 +0000 @@ -7,7 +7,6 @@ #include #include -#include // for size_t #include #include // for integral_constant @@ -16,15 +15,14 @@ #include #include -#include // for CurrentGlobalOrNull +#include #include #include // for GetClass -#include #include #include #include -#include // for JSFUN_CONSTRUCTOR, JS_NewPlainObject, JS_GetFuncti... -#include // for JSProto_Object, JSProtoKey, JSProto_TypeError +#include +#include #include "gjs/jsapi-util.h" #include "gjs/macros.h" @@ -83,10 +81,8 @@ */ [[nodiscard]] static Wrapped* for_js(JSContext* cx, JS::HandleObject wrapper) { - if (!JS_InstanceOf(cx, wrapper, &Base::klass, nullptr)) - return nullptr; - - return JS::GetMaybePtrFromReservedSlot(wrapper, POINTER); + return static_cast( + JS_GetInstancePrivate(cx, wrapper, &Base::klass, nullptr)); } /* @@ -139,45 +135,7 @@ * (It can return null if no private data has been set yet on the wrapper.) */ [[nodiscard]] static Wrapped* for_js_nocheck(JSObject* wrapper) { - return JS::GetMaybePtrFromReservedSlot(wrapper, POINTER); - } - - protected: - // The first reserved slot always stores the private pointer. - static const size_t POINTER = 0; - - /* - * CWrapperPointerOps::has_private: - * - * Returns true if a private C pointer has already been associated with the - * wrapper object. - */ - [[nodiscard]] static bool has_private(JSObject* wrapper) { - return !!JS::GetMaybePtrFromReservedSlot(wrapper, POINTER); - } - - /* - * CWrapperPointerOps::init_private: - * - * Call this to initialize the wrapper object's private C pointer. The - * pointer should not be null. This should not be called twice, without - * calling unset_private() in between. - */ - static void init_private(JSObject* wrapper, Wrapped* ptr) { - assert(!has_private(wrapper) && - "wrapper object should be a fresh object"); - assert(ptr && "private pointer should not be null, use unset_private"); - JS::SetReservedSlot(wrapper, POINTER, JS::PrivateValue(ptr)); - } - - /* - * CWrapperPointerOps::unset_private: - * - * Call this to remove the wrapper object's private C pointer. After calling - * this, it's okay to call init_private() again. - */ - static void unset_private(JSObject* wrapper) { - JS::SetReservedSlot(wrapper, POINTER, JS::UndefinedValue()); + return static_cast(JS::GetPrivate(wrapper)); } }; @@ -204,7 +162,7 @@ * class_spec's flags member. * - static constexpr unsigned constructor_nargs: number of arguments that the * constructor takes. If you implement constructor_impl() then also add this. - * - void finalize_impl(JS::GCContext*, Wrapped*): called when the JS object is + * - void finalize_impl(JSFreeOp*, Wrapped*): called when the JS object is * garbage collected, use this to free the C pointer and do any other cleanup * * Add optional functionality by setting members of class_spec: @@ -256,7 +214,7 @@ Wrapped* priv = Base::constructor_impl(cx, args); if (!priv) return false; - CWrapperPointerOps::init_private(object, priv); + JS::SetPrivate(object, priv); args.rval().setObject(*object); return true; @@ -291,16 +249,17 @@ debug_jsprop(message, gjs_debug_id(id).c_str(), obj); } - static void finalize(JS::GCContext* gcx, JSObject* obj) { + static void finalize(JSFreeOp* fop, JSObject* obj) { Wrapped* priv = Base::for_js_nocheck(obj); // Call only CWrapper's original method here, not any overrides; e.g., // we don't want to deal with a read barrier. CWrapper::debug_lifecycle(priv, obj, "Finalize"); - Base::finalize_impl(gcx, priv); + Base::finalize_impl(fop, priv); - CWrapperPointerOps::unset_private(obj); + // Remove the pointer from the JSObject + JS::SetPrivate(obj, nullptr); } static constexpr JSClassOps class_ops = { @@ -507,7 +466,7 @@ in_obj = gjs_get_import_global(cx); JS::RootedId class_name( cx, gjs_intern_string_to_id(cx, Base::klass.name)); - if (class_name.isVoid() || + if (class_name == JSID_VOID || !JS_DefinePropertyById(cx, in_obj, class_name, ctor_obj, GJS_MODULE_PROP_FLAGS)) return nullptr; @@ -536,8 +495,8 @@ if (!wrapper) return nullptr; - CWrapperPointerOps::init_private(wrapper, - Base::copy_ptr(ptr)); + assert(!JS::GetPrivate(wrapper)); + JS::SetPrivate(wrapper, Base::copy_ptr(ptr)); debug_lifecycle(ptr, wrapper, "from_c_ptr"); diff -Nru gjs-1.74.0/gi/enumeration.cpp gjs-1.72.2/gi/enumeration.cpp --- gjs-1.74.0/gi/enumeration.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/enumeration.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -8,16 +8,14 @@ #include #include -#include #include #include -#include // for JS_NewPlainObject +#include // for JS_DefineProperty, JS_NewPlainObject #include "gi/cwrapper.h" #include "gi/enumeration.h" #include "gi/wrapperutils.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "util/log.h" GJS_JSAPI_RETURN_CONVENTION diff -Nru gjs-1.74.0/gi/function.cpp gjs-1.72.2/gi/function.cpp --- gjs-1.74.0/gi/function.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/function.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -9,6 +9,7 @@ #include // for unique_ptr #include +#include #include #include @@ -22,7 +23,7 @@ #include #include // for JS_ReportOutOfMemory #include -#include +#include #include // for JSPROP_PERMANENT #include #include // for GetRealmFunctionPrototype @@ -32,7 +33,7 @@ #include #include #include -#include // for HandleValueArray +#include // for HandleValueArray, JS_GetElement #include // for JSProtoKey #include "gi/arg-cache.h" @@ -48,7 +49,6 @@ #include "gjs/context.h" #include "gjs/global.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "gjs/profiler-private.h" #include "util/log.h" @@ -109,7 +109,7 @@ GJS_JSAPI_RETURN_CONVENTION static bool call(JSContext* cx, unsigned argc, JS::Value* vp); - static void finalize_impl(JS::GCContext*, Function* priv); + static void finalize_impl(JSFreeOp*, Function* priv); GJS_JSAPI_RETURN_CONVENTION static bool get_length(JSContext* cx, unsigned argc, JS::Value* vp); @@ -149,8 +149,8 @@ static constexpr JSClass klass = { "GIRepositoryFunction", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, - &Function::class_ops, &Function::class_spec}; + JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &Function::class_ops, + &Function::class_spec}; public: GJS_JSAPI_RETURN_CONVENTION @@ -178,15 +178,23 @@ } // namespace Gjs template -static inline void set_ffi_arg(void* result, GIArgument* value) { - if constexpr (std::is_integral_v && std::is_signed_v) { - *static_cast(result) = gjs_arg_get(value); - } else if constexpr (std::is_floating_point_v || std::is_unsigned_v) { - *static_cast(result) = gjs_arg_get(value); - } else if constexpr (std::is_pointer_v) { - *static_cast(result) = - gjs_pointer_to_int(gjs_arg_get(value)); - } +static inline std::enable_if_t && std::is_signed_v> +set_ffi_arg(void* result, GIArgument* value) { + *static_cast(result) = gjs_arg_get(value); +} + +template +static inline std::enable_if_t || + std::is_unsigned_v> +set_ffi_arg(void* result, GIArgument* value) { + *static_cast(result) = gjs_arg_get(value); +} + +template +static inline std::enable_if_t> set_ffi_arg( + void* result, GIArgument* value) { + *static_cast(result) = + gjs_pointer_to_int(gjs_arg_get(value)); } static void @@ -632,13 +640,8 @@ } GjsCallbackTrampoline::~GjsCallbackTrampoline() { - if (m_info && m_closure) { -#if GI_CHECK_VERSION(1, 71, 0) - g_callable_info_destroy_closure(m_info, m_closure); -#else + if (m_info && m_closure) g_callable_info_free_closure(m_info, m_closure); -#endif - } } void GjsCallbackTrampoline::mark_forever() { @@ -649,23 +652,6 @@ s_forever_closure_list.clear(); } -ffi_closure* GjsCallbackTrampoline::create_closure() { - auto callback = [](ffi_cif*, void* result, void** ffi_args, void* data) { - auto** args = reinterpret_cast(ffi_args); - g_assert(data && "Trampoline data is not set"); - Gjs::Closure::Ptr trampoline(static_cast(data), - GjsAutoTakeOwnership()); - - trampoline.as()->callback_closure(args, result); - }; - -#if GI_CHECK_VERSION(1, 71, 0) - return g_callable_info_create_closure(m_info, &m_cif, callback, this); -#else - return g_callable_info_prepare_closure(m_info, &m_cif, callback, this); -#endif -} - bool GjsCallbackTrampoline::initialize() { g_assert(is_valid()); g_assert(!m_closure); @@ -734,7 +720,20 @@ } } - m_closure = create_closure(); + m_closure = g_callable_info_prepare_closure( + m_info, &m_cif, + [](ffi_cif*, void* result, void** ffi_args, void* data) { + auto** args = reinterpret_cast(ffi_args); + g_assert(data && "Trampoline data is not set"); + Gjs::Closure::Ptr trampoline( + static_cast(data), + GjsAutoTakeOwnership()); + + trampoline.as()->callback_closure(args, + result); + }, + this); + return true; } @@ -1154,7 +1153,7 @@ GJS_DEC_COUNTER(function); } -void Function::finalize_impl(JS::GCContext*, Function* priv) { +void Function::finalize_impl(JSFreeOp*, Function* priv) { if (priv == NULL) return; /* we are the prototype, not a real instance, so constructor never called */ delete priv; @@ -1326,7 +1325,8 @@ auto* priv = new Function(info); - Function::init_private(function, priv); + g_assert(!JS::GetPrivate(function) && "Function should be a fresh object"); + JS::SetPrivate(function, priv); debug_lifecycle(function, priv, "Constructor"); diff -Nru gjs-1.74.0/gi/function.h gjs-1.72.2/gi/function.h --- gjs-1.74.0/gi/function.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/function.h 2022-08-08 05:05:12.000000000 +0000 @@ -14,13 +14,13 @@ #include #include -#include // for g_callable_info_get_closure_native_address #include #include #include #include #include +#include // IWYU pragma: keep #include "gi/closure.h" #include "gjs/jsapi-util.h" @@ -49,24 +49,13 @@ ~GjsCallbackTrampoline(); - void* closure() const { -#if GI_CHECK_VERSION(1, 71, 0) - return g_callable_info_get_closure_native_address(m_info, m_closure); -#else - return m_closure; -#endif - } - - ffi_closure* get_ffi_closure() const { - return m_closure; - } + constexpr ffi_closure* closure() const { return m_closure; } void mark_forever(); static void prepare_shutdown(); private: - ffi_closure* create_closure(); GJS_JSAPI_RETURN_CONVENTION bool initialize(); GjsCallbackTrampoline(JSContext* cx, JS::HandleFunction function, GICallableInfo* callable_info, GIScopeType scope, diff -Nru gjs-1.74.0/gi/fundamental.cpp gjs-1.72.2/gi/fundamental.cpp --- gjs-1.74.0/gi/fundamental.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/fundamental.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -13,11 +13,10 @@ #include // for JS_ReportOutOfMemory #include // for WeakCache #include // for GetClass -#include #include #include #include // for UniqueChars -#include // for InformalValueTypeName, JS_NewObjectWithGivenP... +#include // for InformalValueTypeName #include #include "gi/arg-inl.h" @@ -29,7 +28,6 @@ #include "gjs/atoms.h" #include "gjs/context-private.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "util/log.h" @@ -244,13 +242,14 @@ nullptr, // mayResolve &FundamentalBase::finalize, nullptr, // call + nullptr, // hasInstance nullptr, // construct &FundamentalBase::trace }; const struct JSClass FundamentalBase::klass = { "GFundamental_Object", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE, + JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE, &FundamentalBase::class_ops }; // clang-format on diff -Nru gjs-1.74.0/gi/gerror.cpp gjs-1.72.2/gi/gerror.cpp --- gjs-1.74.0/gi/gerror.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/gerror.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -11,20 +11,17 @@ #include #include -#include #include #include #include -#include #include // for JSPROP_ENUMERATE #include #include -#include // for BuildStackString, CaptureCurrentStack #include #include // for UniqueChars #include #include -#include // for InformalValueTypeName, JS_GetClassObject +#include // for JS_DefinePropertyById, JS_GetProp... #include // for JSProtoKey, JSProto_Error, JSProt... #include "gi/arg-inl.h" @@ -36,7 +33,6 @@ #include "gjs/context-private.h" #include "gjs/error-types.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "util/log.h" @@ -196,7 +192,7 @@ const struct JSClass ErrorBase::klass = { "GLib_Error", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &ErrorBase::class_ops }; diff -Nru gjs-1.74.0/gi/gobject.cpp gjs-1.72.2/gi/gobject.cpp --- gjs-1.74.0/gi/gobject.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/gobject.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -10,15 +10,13 @@ #include #include -#include -#include #include // for JSPROP_READONLY #include #include #include #include #include -#include // for JS_NewPlainObject +#include // for JS_SetProperty, JS_DefineProperty #include #include "gi/gobject.h" diff -Nru gjs-1.74.0/gi/gtype.cpp gjs-1.72.2/gi/gtype.cpp --- gjs-1.74.0/gi/gtype.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/gtype.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -12,12 +12,12 @@ #include #include #include // for WeakCache -#include +#include #include // for JSPROP_PERMANENT #include #include #include -#include // for JS_NewObjectWithGivenProto +#include // for JS_GetPropertyById, JS_AtomizeString #include #include "gi/cwrapper.h" @@ -26,7 +26,6 @@ #include "gjs/context-private.h" #include "gjs/global.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "util/log.h" /* @@ -48,7 +47,7 @@ // No private data is allocated, it's stuffed directly in the private field // of JSObject, so nothing to free - static void finalize_impl(JS::GCContext*, void*) {} + static void finalize_impl(JSFreeOp*, void*) {} // Properties @@ -98,8 +97,7 @@ js::ClassSpec::DontDefineConstructor}; static constexpr JSClass klass = { - "GIRepositoryGType", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE, + "GIRepositoryGType", JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE, >ypeObj::class_ops, >ypeObj::class_spec}; GJS_JSAPI_RETURN_CONVENTION @@ -173,7 +171,7 @@ if (!gtype_wrapper) return nullptr; - GTypeObj::init_private(gtype_wrapper, GSIZE_TO_POINTER(gtype)); + JS::SetPrivate(gtype_wrapper, GSIZE_TO_POINTER(gtype)); gjs->gtype_table().put(gtype, gtype_wrapper); diff -Nru gjs-1.74.0/gi/interface.cpp gjs-1.72.2/gi/interface.cpp --- gjs-1.74.0/gi/interface.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/interface.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -9,7 +9,7 @@ #include #include // for JS_ReportOutOfMemory -#include // for PropertyKey, jsid +#include // for JSID_VOID, PropertyKey, jsid #include #include // for UniqueChars @@ -19,7 +19,6 @@ #include "gi/repo.h" #include "gjs/atoms.h" #include "gjs/context-private.h" -#include "gjs/jsapi-util.h" #include "gjs/mem-private.h" InterfacePrototype::InterfacePrototype(GIInterfaceInfo* info, GType gtype) @@ -51,7 +50,7 @@ if (flags & GI_FUNCTION_IS_METHOD) { const char* name = meth_info.name(); jsid id = gjs_intern_string_to_id(cx, name); - if (id.isVoid()) + if (id == JSID_VOID) return false; properties.infallibleAppend(id); } @@ -178,7 +177,7 @@ const struct JSClass InterfaceBase::klass = { "GObject_Interface", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &InterfaceBase::class_ops }; diff -Nru gjs-1.74.0/gi/ns.cpp gjs-1.72.2/gi/ns.cpp --- gjs-1.74.0/gi/ns.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/ns.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -12,6 +12,7 @@ #include #include // for JS_ReportOutOfMemory #include +#include #include // for JSPROP_READONLY #include #include @@ -144,7 +145,7 @@ const char* name = info.name(); jsid id = gjs_intern_string_to_id(cx, name); - if (id.isVoid()) + if (id == JSID_VOID) return false; properties.infallibleAppend(id); } @@ -152,7 +153,7 @@ return true; } - static void finalize_impl(JS::GCContext*, Ns* priv) { + static void finalize_impl(JSFreeOp* fop [[maybe_unused]], Ns* priv) { g_assert(priv && "Finalize called on wrong object"); delete priv; } @@ -202,8 +203,8 @@ static constexpr JSClass klass = { "GIRepositoryNamespace", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE, - &Ns::class_ops, &Ns::class_spec}; + JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE, &Ns::class_ops, + &Ns::class_spec}; public: GJS_JSAPI_RETURN_CONVENTION @@ -218,7 +219,8 @@ return nullptr; auto* priv = new Ns(ns_name); - Ns::init_private(ns, priv); + g_assert(!JS::GetPrivate(ns)); + JS::SetPrivate(ns, priv); gjs_debug_lifecycle(GJS_DEBUG_GNAMESPACE, "ns constructor, obj %p priv %p", ns.get(), priv); diff -Nru gjs-1.74.0/gi/object.cpp gjs-1.72.2/gi/object.cpp --- gjs-1.74.0/gi/object.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/object.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -18,11 +18,11 @@ #include // for move #include +#include #include #include #include -#include // for IsCallable, JS_CallFunctionValue #include #include #include @@ -32,7 +32,7 @@ #include // for MutableWrappedPtrOperations #include #include // for AddAssociatedMemory, RemoveAssoci... -#include +#include #include // for JSPROP_PERMANENT, JSPROP_READONLY #include #include @@ -41,8 +41,8 @@ #include #include #include -#include // for JS_GetFunctionObject, IdVector -#include // for JS_GetObjectFunction, GetFunctionNativeReserved +#include // for IsCallable +#include // for JS_GetObjectFunction, IsFunctionO... #include #include "gi/arg-inl.h" @@ -62,10 +62,8 @@ #include "gjs/context.h" #include "gjs/deprecation.h" #include "gjs/jsapi-class.h" -#include "gjs/jsapi-util.h" #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util-root.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "gjs/profiler-private.h" #include "util/log.h" @@ -81,7 +79,7 @@ #if defined(__x86_64__) && defined(__clang__) /* This isn't meant to be comprehensive, but should trip on at least one CI job * if sizeof(ObjectInstance) is increased. */ -static_assert(sizeof(ObjectInstance) <= 64, +static_assert(sizeof(ObjectInstance) <= 48, "Think very hard before increasing the size of ObjectInstance. " "There can be tens of thousands of them alive in a typical " "gnome-shell run."); @@ -679,7 +677,7 @@ g_assert(v_override_symbol.isSymbol() && "override symbol must be a symbol"); JS::RootedSymbol override_symbol(cx, v_override_symbol.toSymbol()); - JS::RootedId override_id(cx, JS::PropertyKey::Symbol(override_symbol)); + JS::RootedId override_id(cx, SYMBOL_TO_JSID(override_symbol)); JS::RootedObject this_obj(cx); if (!args.computeThis(cx, &this_obj)) @@ -699,7 +697,7 @@ g_assert(v_prototype.isObject() && "prototype must be an object"); JS::RootedObject prototype(cx, &v_prototype.toObject()); - JS::RootedId id(cx, JS::PropertyKey::NonIntAtom(JS_GetFunctionId( + JS::RootedId id(cx, JS::PropertyKey::fromNonIntAtom(JS_GetFunctionId( JS_GetObjectFunction(&args.callee())))); return JS_GetPropertyById(cx, prototype, id, args.rval()); } @@ -723,7 +721,7 @@ JS::RootedObject this_obj(cx); if (!args.computeThis(cx, &this_obj)) return false; - JS::RootedId override_id(cx, JS::PropertyKey::Symbol(symbol)); + JS::RootedId override_id(cx, SYMBOL_TO_JSID(symbol)); return JS_SetPropertyById(cx, this_obj, override_id, args[0]); } @@ -1125,7 +1123,7 @@ if (flags & GI_FUNCTION_IS_METHOD) { const char* name = meth_info.name(); jsid id = gjs_intern_string_to_id(cx, name); - if (id.isVoid()) + if (id == JSID_VOID) return false; properties.infallibleAppend(id); } @@ -1139,7 +1137,7 @@ GjsAutoChar js_name = gjs_hyphen_to_underscore(prop_info.name()); jsid id = gjs_intern_string_to_id(cx, js_name); - if (id.isVoid()) + if (id == JSID_VOID) return false; properties.infallibleAppend(id); } @@ -1164,7 +1162,7 @@ if (flags & GI_FUNCTION_IS_METHOD) { const char* name = meth_info.name(); jsid id = gjs_intern_string_to_id(cx, name); - if (id.isVoid()) + if (id == JSID_VOID) return false; properties.infallibleAppend(id); } @@ -1177,7 +1175,7 @@ GjsAutoChar js_name = gjs_hyphen_to_underscore(prop_info.name()); jsid id = gjs_intern_string_to_id(cx, js_name); - if (id.isVoid()) + if (id == JSID_VOID) return false; properties.infallibleAppend(id); } @@ -1195,7 +1193,7 @@ size_t ix, length; JS::RootedId prop_id(context); JS::RootedValue value(context); - JS::Rooted ids(context, context); + JS::Rooted ids(context); std::unordered_set visited_params; if (!JS_Enumerate(context, props, &ids)) { gjs_throw(context, "Failed to create property iterator for object props hash"); @@ -1584,7 +1582,7 @@ * Private callback, called after the JS engine finishes garbage collection, and * notifies when weak pointers need to be either moved or swept. */ -void ObjectInstance::update_heap_wrapper_weak_pointers(JSTracer* trc, +void ObjectInstance::update_heap_wrapper_weak_pointers(JSContext*, JS::Compartment*, void*) { gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "Weak pointer update callback, " @@ -1596,15 +1594,15 @@ auto locked_queue = ToggleQueue::get_default(); ObjectInstance::remove_wrapped_gobjects_if( - [&trc](ObjectInstance* instance) -> bool { - return instance->weak_pointer_was_finalized(trc); - }, + std::mem_fn(&ObjectInstance::weak_pointer_was_finalized), std::mem_fn(&ObjectInstance::disassociate_js_gobject)); s_wrapped_gobject_list.shrink_to_fit(); } -bool ObjectInstance::weak_pointer_was_finalized(JSTracer* trc) { +bool +ObjectInstance::weak_pointer_was_finalized(void) +{ if (has_wrapper() && !wrapper_is_rooted()) { bool toggle_down_queued, toggle_up_queued; @@ -1615,7 +1613,7 @@ if (!toggle_down_queued && toggle_up_queued) return false; - if (!update_after_gc(trc)) + if (!update_after_gc()) return false; if (toggle_down_queued) @@ -1700,18 +1698,19 @@ return true; } -static void invalidate_closure_vector(std::vector* closures, - void* data, GClosureNotify notify_func) { +static void invalidate_closure_list(std::forward_list* closures, + void* data, GClosureNotify notify_func) { g_assert(closures); g_assert(notify_func); + auto before = closures->before_begin(); for (auto it = closures->begin(); it != closures->end();) { // This will also free the closure data, through the closure // invalidation mechanism, but adding a temporary reference to // ensure that the closure is still valid when calling invalidation // notify callbacks - GjsAutoGClosure closure(*it, GjsAutoTakeOwnership()); - it = closures->erase(it); + GjsAutoGClosure closure(closures->front(), GjsAutoTakeOwnership()); + it = closures->erase_after(before); // Only call the invalidate notifiers that won't touch this vector g_closure_remove_invalidate_notifier(closure, data, notify_func); @@ -1902,14 +1901,14 @@ Gjs::Closure::for_gclosure(closure)->trace(tracer); } -void ObjectInstance::finalize_impl(JS::GCContext* gcx, JSObject* obj) { +void ObjectInstance::finalize_impl(JSFreeOp* fop, JSObject* obj) { GTypeQuery query; type_query_dynamic_safe(&query); if (G_LIKELY(query.type)) JS::RemoveAssociatedMemory(obj, query.instance_size, MemoryUse::GObjectInstanceStruct); - GIWrapperInstance::finalize_impl(gcx, obj); + GIWrapperInstance::finalize_impl(fop, obj); } ObjectInstance::~ObjectInstance() { @@ -1969,7 +1968,7 @@ } ObjectPrototype::~ObjectPrototype() { - invalidate_closure_vector(&m_vfuncs, this, &vfunc_invalidated_notify); + invalidate_closure_list(&m_vfuncs, this, &vfunc_invalidated_notify); g_type_class_unref(g_type_class_peek(m_gtype)); @@ -2106,7 +2105,7 @@ /* This is a weak reference, and will be cleared when the closure is * invalidated */ - m_closures.push_back(closure); + m_closures.push_front(closure); g_closure_add_invalidate_notifier( closure, this, &ObjectInstance::closure_invalidated_notify); @@ -2116,12 +2115,11 @@ void ObjectInstance::closure_invalidated_notify(void* data, GClosure* closure) { // This callback should *only* touch m_closures auto* priv = static_cast(data); - Gjs::remove_one_from_unsorted_vector(&priv->m_closures, closure); + priv->m_closures.remove(closure); } void ObjectInstance::invalidate_closures() { - invalidate_closure_vector(&m_closures, this, &closure_invalidated_notify); - m_closures.shrink_to_fit(); + invalidate_closure_list(&m_closures, this, &closure_invalidated_notify); } bool ObjectBase::connect(JSContext* cx, unsigned argc, JS::Value* vp) { @@ -2534,12 +2532,13 @@ &ObjectBase::finalize, NULL, NULL, + NULL, &ObjectBase::trace, }; const struct JSClass ObjectBase::klass = { "GObject_Object", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE, + JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE, &ObjectBase::class_ops }; @@ -2726,7 +2725,7 @@ ObjectInstance* priv = new ObjectInstance(prototype, obj); - ObjectBase::init_private(obj, priv); + JS::SetPrivate(obj, priv); g_object_ref_sink(gobj); priv->associate_js_gobject(cx, obj, gobj); @@ -3005,7 +3004,7 @@ if (field_info) { gint offset; - void* method_ptr; + gpointer method_ptr; GjsCallbackTrampoline *trampoline; offset = g_field_info_get_offset(field_info); @@ -3026,14 +3025,14 @@ g_assert(std::find(m_vfuncs.begin(), m_vfuncs.end(), trampoline) == m_vfuncs.end() && "This vfunc was already associated with this class"); - m_vfuncs.push_back(trampoline); + m_vfuncs.push_front(trampoline); g_closure_add_invalidate_notifier( trampoline, this, &ObjectPrototype::vfunc_invalidated_notify); g_closure_add_invalidate_notifier( trampoline, nullptr, [](void*, GClosure* closure) { g_closure_unref(closure); }); - *reinterpret_cast(method_ptr) = trampoline->closure(); + *reinterpret_cast(method_ptr) = trampoline->closure(); } return true; @@ -3042,7 +3041,7 @@ void ObjectPrototype::vfunc_invalidated_notify(void* data, GClosure* closure) { // This callback should *only* touch m_vfuncs auto* priv = static_cast(data); - Gjs::remove_one_from_unsorted_vector(&priv->m_vfuncs, closure); + priv->m_vfuncs.remove(closure); } bool diff -Nru gjs-1.74.0/gi/object.h gjs-1.72.2/gi/object.h --- gjs-1.74.0/gi/object.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/object.h 2022-08-08 05:05:12.000000000 +0000 @@ -10,6 +10,7 @@ #include // for size_t #include // for uint32_t +#include #include #include @@ -17,7 +18,6 @@ #include #include -#include #include // for GCHashMap #include // for DefaultHasher #include @@ -39,6 +39,9 @@ namespace JS { class CallArgs; } +namespace js { +class SystemAllocPolicy; +} namespace Gjs { namespace Test { struct ObjectInstance; @@ -170,7 +173,7 @@ return js::DefaultHasher::hash(id.toString()); if (id.isSymbol()) return js::DefaultHasher::hash(id.toSymbol()); - return mozilla::HashGeneric(id.asRawBits()); + return mozilla::HashGeneric(JSID_BITS(id)); } static bool match(jsid id1, jsid id2) { return id1 == id2; } }; @@ -194,7 +197,7 @@ FieldCache m_field_cache; NegativeLookupCache m_unresolvable_cache; // a list of vfunc GClosures installed on this prototype, used when tracing - std::vector m_vfuncs; + std::forward_list m_vfuncs; // a list of interface types explicitly associated with this prototype, // by gjs_add_interface std::vector m_interface_gtypes; @@ -292,7 +295,7 @@ GjsMaybeOwned m_wrapper; // a list of all GClosures installed on this object (from signal connections // and scope-notify callbacks passed to methods), used when tracing - std::vector m_closures; + std::forward_list m_closures; bool m_wrapper_finalized : 1; bool m_gobj_disposed : 1; @@ -333,19 +336,18 @@ void discard_wrapper(void) { m_wrapper.reset(); } void switch_to_rooted(JSContext* cx) { m_wrapper.switch_to_rooted(cx); } void switch_to_unrooted(JSContext* cx) { m_wrapper.switch_to_unrooted(cx); } - [[nodiscard]] bool update_after_gc(JSTracer* trc) { - return m_wrapper.update_after_gc(trc); - } + [[nodiscard]] bool update_after_gc() { return m_wrapper.update_after_gc(); } [[nodiscard]] bool wrapper_is_rooted() const { return m_wrapper.rooted(); } void release_native_object(void); void associate_js_gobject(JSContext* cx, JS::HandleObject obj, GObject* gobj); void disassociate_js_gobject(void); void handle_context_dispose(void); - [[nodiscard]] bool weak_pointer_was_finalized(JSTracer* trc); + [[nodiscard]] bool weak_pointer_was_finalized(); static void ensure_weak_pointer_callback(JSContext* cx); - static void update_heap_wrapper_weak_pointers(JSTracer* trc, - JS::Compartment*, void* data); + static void update_heap_wrapper_weak_pointers(JSContext* cx, + JS::Compartment* compartment, + void* data); public: void toggle_down(void); @@ -419,7 +421,7 @@ GJS_JSAPI_RETURN_CONVENTION bool add_property_impl(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value); - void finalize_impl(JS::GCContext*, JSObject* obj); + void finalize_impl(JSFreeOp* fop, JSObject* obj); void trace_impl(JSTracer* trc); /* JS property getters/setters */ diff -Nru gjs-1.74.0/gi/param.cpp gjs-1.72.2/gi/param.cpp --- gjs-1.74.0/gi/param.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/param.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -4,20 +4,16 @@ #include -#include // for size_t - #include #include #include #include #include // for GetClass -#include #include #include #include // for UniqueChars -#include -#include // for JS_NewObjectForConstructor, JS_NewObjectWithG... +#include // for JS_GetPropertyById #include // for JSProto_TypeError #include "gi/cwrapper.h" @@ -29,15 +25,11 @@ #include "gjs/context-private.h" #include "gjs/jsapi-class.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "util/log.h" extern struct JSClass gjs_param_class; -// Reserved slots -static const size_t POINTER = 0; - struct Param : GjsAutoParam { explicit Param(GParamSpec* param) : GjsAutoParam(param, GjsAutoTakeOwnership()) {} @@ -45,10 +37,8 @@ [[nodiscard]] static GParamSpec* param_value(JSContext* cx, JS::HandleObject obj) { - if (!JS_InstanceOf(cx, obj, &gjs_param_class, nullptr)) - return nullptr; - - auto* priv = JS::GetMaybePtrFromReservedSlot(obj, POINTER); + auto* priv = static_cast( + JS_GetInstancePrivate(cx, obj, &gjs_param_class, nullptr)); return priv ? priv->get() : nullptr; } @@ -123,15 +113,15 @@ return true; } -static void param_finalize(JS::GCContext*, JSObject* obj) { - Param* priv = JS::GetMaybePtrFromReservedSlot(obj, POINTER); +static void param_finalize(JSFreeOp*, JSObject* obj) { + Param* priv = static_cast(JS::GetPrivate(obj)); gjs_debug_lifecycle(GJS_DEBUG_GPARAM, "finalize, obj %p priv %p", obj, priv); if (!priv) return; /* wrong class? */ GJS_DEC_COUNTER(param); - JS::SetReservedSlot(obj, POINTER, JS::UndefinedValue()); + JS::SetPrivate(obj, nullptr); delete priv; } @@ -150,8 +140,9 @@ struct JSClass gjs_param_class = { "GObject_ParamSpec", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, - &gjs_param_class_ops}; + JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, + &gjs_param_class_ops +}; GJS_JSAPI_RETURN_CONVENTION static JSObject* @@ -229,7 +220,7 @@ GJS_INC_COUNTER(param); auto* priv = new Param(gparam); - JS::SetReservedSlot(obj, POINTER, JS::PrivateValue(priv)); + JS::SetPrivate(obj, priv); gjs_debug(GJS_DEBUG_GPARAM, "JSObject created with param instance %p type %s", gparam, diff -Nru gjs-1.74.0/gi/private.cpp gjs-1.72.2/gi/private.cpp --- gjs-1.74.0/gi/private.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/private.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -12,13 +12,12 @@ #include // for JS::GetArrayLength, #include -#include #include #include #include #include // for UniqueChars #include -#include // for JS_NewPlainObject +#include // for JS_GetElement #include "gi/gobject.h" #include "gi/gtype.h" @@ -31,7 +30,6 @@ #include "gjs/context-private.h" #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" /* gi/private.cpp - private "imports._gi" module with operations that we need * to use from JS in order to create GObject classes, but should not be exposed diff -Nru gjs-1.74.0/gi/repo.cpp gjs-1.72.2/gi/repo.cpp --- gjs-1.74.0/gi/repo.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/repo.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -15,14 +15,11 @@ #include #include -#include // for JS_CallFunctionValue #include #include #include -#include // for CurrentGlobalOrNull -#include // for PropertyKey +#include // for JSID_VOID #include // for GetClass -#include #include // for JSPROP_PERMANENT, JSPROP_RESOLVING #include #include @@ -31,7 +28,7 @@ #include #include #include -#include // for JS_NewPlainObject, JS_NewObject +#include // for JS_DefinePropertyById, JS_GetProp... #include "gi/arg.h" #include "gi/boxed.h" @@ -49,7 +46,6 @@ #include "gjs/context-private.h" #include "gjs/global.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/module.h" #include "util/log.h" @@ -485,7 +481,7 @@ } JS::RootedId ns_name(context, gjs_intern_string_to_id(context, ns)); - if (ns_name.isVoid()) + if (ns_name == JSID_VOID) return nullptr; return gjs_lookup_namespace_object_by_name(context, ns_name); } diff -Nru gjs-1.74.0/gi/union.cpp gjs-1.72.2/gi/union.cpp --- gjs-1.74.0/gi/union.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/union.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -5,6 +5,7 @@ #include #include +#include // for g_atomic_rc_box_acquire, ... #include #include @@ -18,7 +19,6 @@ #include "gi/repo.h" #include "gi/union.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "util/log.h" @@ -148,7 +148,7 @@ const struct JSClass UnionBase::klass = { "GObject_Union", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE, + JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE, &UnionBase::class_ops }; // clang-format on diff -Nru gjs-1.74.0/gi/utils-inl.h gjs-1.72.2/gi/utils-inl.h --- gjs-1.74.0/gi/utils-inl.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/utils-inl.h 2022-08-08 05:05:12.000000000 +0000 @@ -8,6 +8,8 @@ #include +#include // IWYU pragma: keep (for find) +#include // IWYU pragma: keep #include // IWYU pragma: keep (for swap) #include diff -Nru gjs-1.74.0/gi/value.cpp gjs-1.72.2/gi/value.cpp --- gjs-1.74.0/gi/value.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/value.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -18,7 +18,6 @@ #include #include #include // for RootedVector -#include #include #include #include @@ -47,7 +46,6 @@ #include "gjs/context-private.h" #include "gjs/context.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/objectbox.h" #include "util/log.h" diff -Nru gjs-1.74.0/gi/wrapperutils.h gjs-1.72.2/gi/wrapperutils.h --- gjs-1.74.0/gi/wrapperutils.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gi/wrapperutils.h 2022-08-08 05:05:12.000000000 +0000 @@ -22,10 +22,9 @@ #include #include #include -#include // for JS_DefineFunctionById #include #include -#include // for JS_GetPrototype +#include // for JS_GetPrototype, JS_DefineFunctionById #include // for JSProto_TypeError #include "gi/arg-inl.h" @@ -395,7 +394,7 @@ * necessary to include a finalize_impl() function in Prototype or Instance. * Any needed finalization should be done in ~Prototype() and ~Instance(). */ - static void finalize(JS::GCContext* gcx, JSObject* obj) { + static void finalize(JSFreeOp* fop, JSObject* obj) { Base* priv = Base::for_js_nocheck(obj); if (!priv) return; // construction didn't finish @@ -405,11 +404,12 @@ static_cast(priv)->debug_lifecycle(obj, "Finalize"); if (priv->is_prototype()) - priv->to_prototype()->finalize_impl(gcx, obj); + priv->to_prototype()->finalize_impl(fop, obj); else - priv->to_instance()->finalize_impl(gcx, obj); + priv->to_instance()->finalize_impl(fop, obj); - Base::unset_private(obj); + // Remove the pointer from the JSObject + JS::SetPrivate(obj, nullptr); } /* @@ -902,7 +902,7 @@ // a garbage collection or error happens subsequently, then this object // might be traced and we would end up dereferencing a null pointer. Prototype* proto = priv.release(); - Prototype::init_private(prototype, proto); + JS::SetPrivate(prototype, proto); if (!gjs_wrapper_define_gtype_prop(cx, constructor, gtype)) return nullptr; @@ -949,7 +949,7 @@ return nullptr; Prototype* proto = priv.release(); - Prototype::init_private(prototype, proto); + JS::SetPrivate(prototype, proto); if (!proto->define_static_methods(cx, constructor)) return nullptr; @@ -1013,7 +1013,7 @@ // JSClass operations protected: - void finalize_impl(JS::GCContext*, JSObject*) { release(); } + void finalize_impl(JSFreeOp*, JSObject*) { release(); } // Override if necessary void trace_impl(JSTracer*) {} @@ -1060,22 +1060,24 @@ */ [[nodiscard]] static Instance* new_for_js_object(JSContext* cx, JS::HandleObject obj) { + g_assert(!JS::GetPrivate(obj)); Prototype* prototype = Prototype::for_js_prototype(cx, obj); auto* priv = new Instance(prototype, obj); // Init the private variable before we do anything else. If a garbage // collection happens when calling the constructor, then this object // might be traced and we would end up dereferencing a null pointer. - Instance::init_private(obj, priv); + JS::SetPrivate(obj, priv); return priv; } [[nodiscard]] static Instance* new_for_js_object(Prototype* prototype, JS::HandleObject obj) { + g_assert(!JS::GetPrivate(obj)); auto* priv = new Instance(prototype, obj); - Instance::init_private(obj, priv); + JS::SetPrivate(obj, priv); return priv; } @@ -1108,7 +1110,7 @@ // JSClass operations protected: - void finalize_impl(JS::GCContext*, JSObject*) { + void finalize_impl(JSFreeOp*, JSObject*) { delete static_cast(this); } diff -Nru gjs-1.74.0/.gitignore gjs-1.72.2/.gitignore --- gjs-1.74.0/.gitignore 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/.gitignore 2022-08-08 05:05:12.000000000 +0000 @@ -1,5 +1,3 @@ # SPDX-License-Identifier: MIT OR LGPL-2.0-or-later # SPDX-FileCopyrightText: 2020 Philip Chimento /tools/node_modules -# artifact from ci-templates: -/container-build-report.xml diff -Nru gjs-1.74.0/.gitlab-ci.yml gjs-1.72.2/.gitlab-ci.yml --- gjs-1.74.0/.gitlab-ci.yml 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/.gitlab-ci.yml 2022-08-08 05:05:12.000000000 +0000 @@ -2,7 +2,7 @@ # SPDX-FileCopyrightText: 2017 Claudio André --- include: - - remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/c5626190ec14b475271288dda7a7dae8dbe0cd76/templates/alpine.yml' + - remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/7ea696055e322cc7aa4bcbe5422b56a198c4bdff/templates/alpine.yml' stages: - prepare @@ -14,7 +14,7 @@ .gjs-alpine: variables: - FDO_DISTRIBUTION_TAG: '2022-07-23.0' + FDO_DISTRIBUTION_TAG: '2021-08-18.0' FDO_UPSTREAM_REPO: GNOME/gjs build-alpine-image: @@ -31,7 +31,7 @@ mkdir -p /cwd .coverage: &coverage - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: coverage: '/^ lines.*(\d+\.\d+\%)/' script: @@ -44,19 +44,13 @@ artifacts: name: log_coverage when: always - reports: - junit: _coverage_build/meson-logs/testlog*.junit.xml - expose_as: 'Coverage Report' paths: - - _coverage/html/index.html - _coverage/html - - _coverage_build/meson-logs + - _coverage_build/meson-logs/*log*.txt .build: &build when: on_success artifacts: - reports: - junit: _build/meson-logs/testlog*.junit.xml name: log when: always paths: @@ -75,9 +69,9 @@ build_recommended: <<: *build stage: source_check - image: registry.gitlab.gnome.org/gnome/gjs:job-2190518_fedora.mozjs102-debug # pinned on purpose + image: registry.gitlab.gnome.org/gnome/gjs:job-1740076_fedora.mozjs91-debug # pinned on purpose variables: - TEST_OPTS: --verbose --no-stdsplit --print-errorlogs --setup=verbose + TEST_OPTS: --verbose --no-stdsplit --print-errorlogs except: - schedules @@ -86,10 +80,10 @@ stage: test tags: - asan # LSAN needs CAP_SYS_PTRACE - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: CONFIG_OPTS: -Db_sanitize=address,undefined - TEST_OPTS: --timeout-multiplier=3 --setup=verbose + TEST_OPTS: --timeout-multiplier=3 except: - schedules @@ -100,10 +94,10 @@ allow_failure: true tags: - asan # TSAN needs CAP_SYS_PTRACE - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: CONFIG_OPTS: -Db_sanitize=thread - TEST_OPTS: --timeout-multiplier=3 --setup=verbose + TEST_OPTS: --timeout-multiplier=3 except: - schedules @@ -113,7 +107,7 @@ build_maximal: <<: *build stage: test - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: CC: clang CXX: clang++ @@ -129,19 +123,18 @@ build_minimal: <<: *build stage: test - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102 + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91 variables: CONFIG_OPTS: >- -Dbuildtype=release -Dcairo=disabled -Dreadline=disabled -Dprofiler=disabled - TEST_OPTS: --setup=verbose except: - schedules build_unity: <<: *build stage: test - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102 + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91 variables: # unity-size here is forced to use an high number to check whether we can # join all the sources together, but should not be used in real world to @@ -149,7 +142,6 @@ CONFIG_OPTS: >- -Dprofiler=disabled --unity on --unity-size=10000 - TEST_OPTS: --setup=verbose except: - schedules @@ -253,7 +245,7 @@ iwyu: when: on_success stage: source_check - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug script: - test/test-ci.sh UPSTREAM_BASE - meson setup _build -Db_pch=false @@ -304,7 +296,7 @@ iwyu-full: when: manual stage: manual - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug script: - meson setup _build - ./tools/run_iwyu.sh @@ -316,12 +308,12 @@ stage: manual tags: - asan # LSAN needs CAP_SYS_PTRACE - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: CC: clang CXX: clang++ CONFIG_OPTS: -Db_sanitize=address,undefined -Db_lundef=false - TEST_OPTS: --timeout-multiplier=3 --setup=verbose + TEST_OPTS: --timeout-multiplier=3 when: manual except: - schedules @@ -329,7 +321,7 @@ installed_tests: <<: *build stage: manual - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: CONFIG_OPTS: -Dinstalled_tests=true -Dprefix=/usr TEST: skip @@ -345,7 +337,7 @@ valgrind: <<: *build stage: manual - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: TEST_OPTS: --setup=valgrind allow_failure: true @@ -357,7 +349,7 @@ zeal_2: <<: *build stage: manual - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: TEST_OPTS: --setup=extra_gc when: manual @@ -367,7 +359,7 @@ zeal_4: <<: *build stage: manual - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: TEST_OPTS: --setup=pre_verify when: manual @@ -377,7 +369,7 @@ zeal_11: <<: *build stage: manual - image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs102-debug + image: registry.gitlab.gnome.org/gnome/gjs:fedora.mozjs91-debug variables: TEST_OPTS: --setup=post_verify when: manual @@ -388,7 +380,7 @@ # Create CI Docker Images # ############################################# .Docker image template: &create_docker_image - image: quay.io/freedesktop.org/ci-templates:container-build-base-2022-05-25.0 + image: registry.freedesktop.org/freedesktop/ci-templates/x86_64/buildah:2020-10-30.1 stage: deploy only: variables: @@ -424,23 +416,11 @@ variables: <<: *docker_variables DOCKERFILE: test/extra/Dockerfile + ARGS: --build-arg MOZJS_BUILDDEPS=mozjs78 fedora.mozjs91-debug: <<: *create_docker_image variables: <<: *docker_variables DOCKERFILE: test/extra/Dockerfile.debug - -fedora.mozjs102: - <<: *create_docker_image - variables: - <<: *docker_variables - DOCKERFILE: test/extra/Dockerfile - ARGS: --build-arg MOZJS_BRANCH=mozjs102 --build-arg MOZJS_BUILDDEPS=mozjs91 - -fedora.mozjs102-debug: - <<: *create_docker_image - variables: - <<: *docker_variables - DOCKERFILE: test/extra/Dockerfile.debug - ARGS: --build-arg MOZJS_BRANCH=mozjs102 --build-arg MOZJS_BUILDDEPS=mozjs91 + ARGS: --build-arg MOZJS_BUILDDEPS=mozjs78 diff -Nru gjs-1.74.0/gjs/atoms.cpp gjs-1.72.2/gjs/atoms.cpp --- gjs-1.74.0/gjs/atoms.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/atoms.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -31,7 +31,7 @@ JS::Symbol* symbol = JS::NewSymbol(cx, descr); if (!symbol) return false; - m_jsid = JS::Heap{JS::PropertyKey::Symbol(symbol)}; + m_jsid = JS::Heap{SYMBOL_TO_JSID(symbol)}; return true; } diff -Nru gjs-1.74.0/gjs/byteArray.cpp gjs-1.72.2/gjs/byteArray.cpp --- gjs-1.74.0/gjs/byteArray.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/byteArray.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -6,18 +6,18 @@ #include +#include #include #include #include #include -#include #include #include #include #include // for UniqueChars #include -#include // for JS_NewPlainObject +#include // for JS_DefineFunctionById, JS_DefineFun... #include "gi/boxed.h" #include "gjs/atoms.h" @@ -26,7 +26,6 @@ #include "gjs/deprecation.h" #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/text-encoding.h" #include "util/misc.h" // for _gjs_memdup2 diff -Nru gjs-1.74.0/gjs/context.cpp gjs-1.72.2/gjs/context.cpp --- gjs-1.74.0/gjs/context.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/context.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -36,7 +36,6 @@ #endif #include // for SystemAllocPolicy -#include // for Call, JS_CallFunctionValue #include // for UndefinedHandleValue #include #include @@ -47,15 +46,12 @@ #include // for JS_GC, JS_AddExtraGCRootsTr... #include // for WeakCache #include // for RootedVector -#include // for CurrentGlobalOrNull #include #include #include // for JobQueue::SavedJobQueue -#include #include // for JSPROP_PERMANENT, JSPROP_RE... #include #include -#include #include #include #include @@ -63,7 +59,7 @@ #include #include #include -#include // for JS_GetFunctionObject, JS_Ge... +#include // for Call, CurrentGlobalOrNull #include // for ScriptEnvironmentPreparer #include @@ -437,7 +433,7 @@ m_gtype_table->clear(); /* Do a full GC here before tearing down, since once we do - * that we may not have the JS::GetReservedSlot(, 0) to access the + * that we may not have the JS::GetPrivate() to access the * context */ gjs_debug(GJS_DEBUG_CONTEXT, "Final triggered GC"); diff -Nru gjs-1.74.0/gjs/context-private.h gjs-1.72.2/gjs/context-private.h --- gjs-1.74.0/gjs/context-private.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/context-private.h 2022-08-08 05:05:12.000000000 +0000 @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -33,7 +32,6 @@ #include #include #include // for ScriptEnvironmentPreparer -#include #include "gi/closure.h" #include "gjs/context.h" @@ -43,6 +41,9 @@ #include "gjs/profiler.h" #include "gjs/promise.h" +namespace js { +class SystemAllocPolicy; +} class GjsAtoms; class JSTracer; diff -Nru gjs-1.74.0/gjs/coverage.cpp gjs-1.72.2/gjs/coverage.cpp --- gjs-1.74.0/gjs/coverage.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/coverage.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -14,7 +14,6 @@ #include #include // for JS_AddExtraGCRootsTracer, JS_Remove... -#include #include #include #include @@ -22,7 +21,7 @@ #include // for UniqueChars #include #include // for EnableCodeCoverage -#include // for JS_WrapObject +#include // for JS_SetPropertyById #include "gjs/atoms.h" #include "gjs/context-private.h" diff -Nru gjs-1.74.0/gjs/debugger.cpp gjs-1.72.2/gjs/debugger.cpp --- gjs-1.74.0/gjs/debugger.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/debugger.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -23,7 +22,7 @@ #include #include // for UniqueChars #include -#include // for JS_WrapObject +#include // for JS_DefineFunctions, JS_SetPropertyById #include "gjs/atoms.h" #include "gjs/context-private.h" diff -Nru gjs-1.74.0/gjs/deprecation.cpp gjs-1.72.2/gjs/deprecation.cpp --- gjs-1.74.0/gjs/deprecation.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/deprecation.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -16,11 +16,11 @@ #include #include #include -#include // for CaptureCurrentStack, MaxFrames #include #include // for UniqueChars #include #include +#include // for MaxFrames, CaptureCurrentStack #include "gjs/deprecation.h" #include "gjs/macros.h" @@ -34,7 +34,8 @@ "this would have interpreted the bytes of the array as a string, but that " "is nonstandard. In the future this will return the bytes as " "comma-separated digits. For the time being, the old behavior has been " - "preserved, but please fix your code anyway to use TextDecoder.\n" + "preserved, but please fix your code anyway to explicitly call ByteArray" + ".toString(array).\n" "(Note that array.toString() may have been called implicitly.)", // DeprecatedGObjectProperty: diff -Nru gjs-1.74.0/gjs/engine.cpp gjs-1.72.2/gjs/engine.cpp --- gjs-1.74.0/gjs/engine.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/engine.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -21,11 +21,10 @@ #include // for JS_Init, JS_ShutDown #include #include -#include // for JS_SetNativeStackQuota #include #include #include -#include // for JS_SetGlobalJitCompilerOption +#include // for InitSelfHostedCode, JS_Destr... #include #include "gjs/context-private.h" @@ -33,7 +32,7 @@ #include "gjs/jsapi-util.h" #include "util/log.h" -static void gjs_finalize_callback(JS::GCContext*, JSFinalizeStatus status, +static void gjs_finalize_callback(JSFreeOp*, JSFinalizeStatus status, void* data) { auto* gjs = static_cast(data); gjs->set_finalize_status(status); @@ -89,13 +88,10 @@ { switch (fdwReason) { - case DLL_PROCESS_ATTACH: { - gjs_dll = hinstDLL; - const char* reason = JS_InitWithFailureDiagnostic(); - if (reason) - g_error("Could not initialize JavaScript: %s", reason); - gjs_is_inited = true; - } break; + case DLL_PROCESS_ATTACH: + gjs_dll = hinstDLL; + gjs_is_inited = JS_Init(); + break; case DLL_THREAD_DETACH: JS_ShutDown (); @@ -113,9 +109,8 @@ class GjsInit { public: GjsInit() { - const char* reason = JS_InitWithFailureDiagnostic(); - if (reason) - g_error("Could not initialize JavaScript: %s", reason); + if (!JS_Init()) + g_error("Could not initialize Javascript"); } ~GjsInit() { @@ -172,7 +167,12 @@ if (enable_jit) { gjs_debug(GJS_DEBUG_CONTEXT, "Enabling JIT"); } - JS::ContextOptionsRef(cx).setAsmJS(enable_jit); + JS::ContextOptionsRef(cx) + .setAsmJS(enable_jit) + .setTopLevelAwait(true) + .setClassStaticBlocks(true) + .setPrivateClassFields(true) + .setPrivateClassMethods(true); uint32_t value = enable_jit ? 1 : 0; diff -Nru gjs-1.74.0/gjs/gjs_pch.hh gjs-1.72.2/gjs/gjs_pch.hh --- gjs-1.74.0/gjs/gjs_pch.hh 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/gjs_pch.hh 2022-08-08 05:05:12.000000000 +0000 @@ -10,9 +10,8 @@ #include #include #include +#include #include -#include -#include #include #include #include @@ -53,7 +52,6 @@ #include #include #include -#include #include #include #include @@ -63,14 +61,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include @@ -82,16 +78,13 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include -#include #include #include #include @@ -101,6 +94,7 @@ #include #include #include +#include #include #include #include @@ -108,7 +102,6 @@ #include #include #include -#include #include #include #include @@ -116,11 +109,8 @@ #include #include #include -#include -#include #include #include -#include #ifdef HAVE_READLINE_READLINE_H #include #include diff -Nru gjs-1.74.0/gjs/global.cpp gjs-1.72.2/gjs/global.cpp --- gjs-1.74.0/gjs/global.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/global.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -16,12 +16,9 @@ #include #include #include -#include // for JS_DefineDebuggerObject -#include // for CurrentGlobalOrNull, JS_NewGlobalObject #include #include #include -#include #include // for JSPROP_PERMANENT, JSPROP_RE... #include #include // for GetObjectRealmOrNull, SetRealmPrivate @@ -30,7 +27,7 @@ #include #include #include // for UniqueChars -#include // for JS_IdToValue, JS_InitReflectParse +#include // for AutoSaveExceptionState, ... #include "gjs/atoms.h" #include "gjs/context-private.h" @@ -38,7 +35,6 @@ #include "gjs/global.h" #include "gjs/internal.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/native.h" namespace mozilla { @@ -110,8 +106,12 @@ JS::SourceOwnership::TakeOwnership)) return false; + JS::RootedScript compiled_script(cx, JS::Compile(cx, options, source)); + if (!compiled_script) + return false; + JS::RootedValue ignored(cx); - return JS::Evaluate(cx, options, source, &ignored); + return JS::CloneAndExecuteScript(cx, compiled_script, &ignored); } GJS_JSAPI_RETURN_CONVENTION diff -Nru gjs-1.74.0/gjs/global.h gjs-1.72.2/gjs/global.h --- gjs-1.74.0/gjs/global.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/global.h 2022-08-08 05:05:12.000000000 +0000 @@ -42,8 +42,6 @@ // Stores the module registry (a Map object) MODULE_REGISTRY, NATIVE_REGISTRY, - // prettyPrint() function defined in JS but used internally in C++ - PRETTY_PRINT_FUNC, PROTOTYPE_gtype, PROTOTYPE_importer, PROTOTYPE_function, diff -Nru gjs-1.74.0/gjs/importer.cpp gjs-1.72.2/gjs/importer.cpp --- gjs-1.74.0/gjs/importer.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/importer.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -24,10 +24,8 @@ #include #include // for JS_ReportOutOfMemory #include -#include // for CurrentGlobalOrNull #include // for PropertyKey #include // for GetClass -#include #include #include #include @@ -36,7 +34,7 @@ #include #include // for UniqueChars #include -#include // for JS_NewPlainObject, IdVector, JS_... +#include // for JS_DefinePropertyById, JS_DefineP... #include // for JSProto_Error #include #include @@ -46,7 +44,6 @@ #include "gjs/global.h" #include "gjs/importer.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/module.h" #include "gjs/native.h" #include "util/log.h" @@ -174,9 +171,9 @@ module_path, attrs)) return false; - JS::RootedId to_string_tag_name( - context, JS::PropertyKey::Symbol(JS::GetWellKnownSymbol( - context, JS::SymbolCode::toStringTag))); + JS::RootedId to_string_tag_name(context, + SYMBOL_TO_JSID(JS::GetWellKnownSymbol(context, + JS::SymbolCode::toStringTag))); return JS_DefinePropertyById(context, module_obj, to_string_tag_name, to_string_tag, attrs); } @@ -286,7 +283,7 @@ cx, gjs_get_native_registry(gjs_get_import_global(cx))); JS::RootedId id(cx, gjs_intern_string_to_id(cx, parse_name)); - if (id.isVoid()) + if (id == JSID_VOID) return false; JS::RootedObject module(cx); @@ -695,7 +692,7 @@ if (g_file_info_get_file_type(info) == G_FILE_TYPE_DIRECTORY) { jsid id = gjs_intern_string_to_id(context, filename); - if (id.isVoid()) + if (id == JSID_VOID) return false; if (!properties.append(id)) { JS_ReportOutOfMemory(context); @@ -706,7 +703,7 @@ GjsAutoChar filename_noext = g_strndup(filename, strlen(filename) - 3); jsid id = gjs_intern_string_to_id(context, filename_noext); - if (id.isVoid()) + if (id == JSID_VOID) return false; if (!properties.append(id)) { JS_ReportOutOfMemory(context); diff -Nru gjs-1.74.0/gjs/internal.cpp gjs-1.72.2/gjs/internal.cpp --- gjs-1.74.0/gjs/internal.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/internal.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -4,53 +4,49 @@ #include "gjs/internal.h" #include - -#include // for size_t -#include - -#include // for unique_ptr - #include +#include #include #include - -#include // for JS_CallFunction -#include -#include +#include +#include #include #include -#include -#include // for JS_AddExtraGCRootsTracer +#include +#include // for RootedVector #include #include -#include #include -#include #include #include -#include -#include #include -#include // for UniqueChars -#include -#include -#include // for JS_NewPlainObject, JS_ObjectIsFunction -#include // for JS_GetObjectFunction, SetFunctionNativeReserved -#include // for JSProto_Error +#include +#include // for JS_DefinePropertyById, ... +#include +#include // for size_t +#include // for ssize_t + +#include // for unique_ptr +#include // for u16string +#include +#include "gjs/byteArray.h" #include "gjs/context-private.h" +#include "gjs/context.h" #include "gjs/engine.h" +#include "gjs/error-types.h" #include "gjs/global.h" +#include "gjs/importer.h" #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" +#include "gjs/mainloop.h" +#include "gjs/mem-private.h" #include "gjs/module.h" +#include "gjs/native.h" #include "util/log.h" #include "util/misc.h" -namespace mozilla { -union Utf8Unit; -} +#include "gi/repo.h" // NOTE: You have to be very careful in this file to only do operations within // the correct global! diff -Nru gjs-1.74.0/gjs/internal.h gjs-1.72.2/gjs/internal.h --- gjs-1.74.0/gjs/internal.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/internal.h 2022-08-08 05:05:12.000000000 +0000 @@ -7,6 +7,7 @@ #include #include +#include #include "gjs/macros.h" diff -Nru gjs-1.74.0/gjs/jsapi-dynamic-class.cpp gjs-1.72.2/gjs/jsapi-dynamic-class.cpp --- gjs-1.74.0/gjs/jsapi-dynamic-class.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/jsapi-dynamic-class.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -9,18 +9,16 @@ #include -#include #include // for JSNative #include #include #include // for GetClass -#include // for JS_DefineFunctions, JS_DefinePro... #include // for GetRealmObjectPrototype #include #include #include #include -#include // for JS_GetFunctionObject, JS_GetPrototype +#include // for JS_DefineFunctions, JS_DefineProp... #include // for GetFunctionNativeReserved, NewFun... #include // for JSProto_TypeError diff -Nru gjs-1.74.0/gjs/jsapi-util.cpp gjs-1.72.2/gjs/jsapi-util.cpp --- gjs-1.74.0/gjs/jsapi-util.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/jsapi-util.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -17,7 +17,6 @@ #include // for move #include -#include #include #include #include @@ -30,21 +29,22 @@ #include // for RootedVector #include // for DefaultHasher #include // for GetClass -#include #include -#include // for BuildStackString #include #include #include #include -#include // for JS_InstanceOf +#include // for JS_GetPropertyById, JS_InstanceOf #include // for ProtoKeyToClass #include // for HashSet::AddPtr #include "gjs/atoms.h" #include "gjs/context-private.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" + +namespace js { +class SystemAllocPolicy; +} static void throw_property_lookup_error(JSContext *cx, @@ -243,6 +243,121 @@ return array; } +/** + * gjs_string_readable: + * + * Return a string that can be read back by gjs-console; for + * JS strings that contain valid Unicode, we return a UTF-8 formatted + * string. Otherwise, we return one where non-ASCII-printable bytes + * are \x escaped. + * + */ +[[nodiscard]] static std::string gjs_string_readable(JSContext* context, + JS::HandleString string) { + std::string buf(1, '"'); + + JS::UniqueChars chars(JS_EncodeStringToUTF8(context, string)); + if (!chars) { + /* I'm not sure this code will actually ever be reached except in the + * case of OOM, since JS_EncodeStringToUTF8() seems to happily output + * non-valid UTF-8 bytes. However, let's leave this in, since + * SpiderMonkey may decide to do validation in the future. */ + + /* Find out size of buffer to allocate, not counting 0-terminator */ + size_t len = JS_PutEscapedString(context, NULL, 0, string, '"'); + char *escaped = g_new(char, len + 1); + + JS_PutEscapedString(context, escaped, len, string, '"'); + buf += escaped; + g_free(escaped); + } else { + buf += chars.get(); + } + + return buf + '"'; +} + +[[nodiscard]] static std::string _gjs_g_utf8_make_valid(const char* name) { + const char *remainder, *invalid; + int remaining_bytes, valid_bytes; + + g_return_val_if_fail (name != NULL, ""); + + remainder = name; + remaining_bytes = strlen (name); + + if (remaining_bytes == 0) + return std::string(name); + + std::string buf; + buf.reserve(remaining_bytes); + while (remaining_bytes != 0) { + if (g_utf8_validate (remainder, remaining_bytes, &invalid)) + break; + valid_bytes = invalid - remainder; + + buf.append(remainder, valid_bytes); + /* append U+FFFD REPLACEMENT CHARACTER */ + buf += "\357\277\275"; + + remaining_bytes -= valid_bytes + 1; + remainder = invalid + 1; + } + + buf += remainder; + + g_assert(g_utf8_validate(buf.c_str(), -1, nullptr)); + + return buf; +} + +/** + * gjs_value_debug_string: + * @context: + * @value: Any JavaScript value + * + * Returns: A UTF-8 encoded string describing @value + */ +std::string gjs_value_debug_string(JSContext* context, JS::HandleValue value) { + /* Special case debug strings for strings */ + if (value.isString()) { + JS::RootedString str(context, value.toString()); + return gjs_string_readable(context, str); + } + + JS::RootedString str(context, JS::ToString(context, value)); + + if (!str) { + JS_ClearPendingException(context); + str = JS_ValueToSource(context, value); + } + + if (!str) { + if (value.isObject()) { + /* Specifically the Call object (see jsfun.c in spidermonkey) + * does not have a toString; there may be others also. + */ + const JSClass* klass = JS::GetClass(&value.toObject()); + if (klass != NULL) { + str = JS_NewStringCopyZ(context, klass->name); + JS_ClearPendingException(context); + if (!str) + return "[out of memory copying class name]"; + } else { + gjs_log_exception(context); + return "[unknown object]"; + } + } else { + return "[unknown non-object]"; + } + } + + g_assert(str); + + JS::UniqueChars bytes = JS_EncodeStringToUTF8(context, str); + return _gjs_g_utf8_make_valid(bytes.get()); +} + // Helper function: perform ToString on an exception (which may not even be an // object), except if it is an InternalError, which would throw in ToString. GJS_JSAPI_RETURN_CONVENTION diff -Nru gjs-1.74.0/gjs/jsapi-util-error.cpp gjs-1.72.2/gjs/jsapi-util-error.cpp --- gjs-1.74.0/gjs/jsapi-util-error.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/jsapi-util-error.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -8,21 +8,17 @@ #include -#include -#include #include #include #include #include // for GCHashSet #include // for DefaultHasher -#include #include -#include // for BuildStackString #include #include // for UniqueChars #include -#include // for JS_GetClassObject -#include // for JSProtoKey, JSProto_Error, JSProto... +#include // for BuildStackString, Construct, JS_GetClassObject +#include // for JSProtoKey, JSProto_Error, JSProto... #include // for HashSet<>::AddPtr #include "gjs/atoms.h" @@ -32,6 +28,10 @@ #include "util/log.h" #include "util/misc.h" +namespace js { +class SystemAllocPolicy; +} + using CauseSet = JS::GCHashSet, js::SystemAllocPolicy>; diff -Nru gjs-1.74.0/gjs/jsapi-util.h gjs-1.72.2/gjs/jsapi-util.h --- gjs-1.74.0/gjs/jsapi-util.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/jsapi-util.h 2022-08-08 05:05:12.000000000 +0000 @@ -450,6 +450,9 @@ void gjs_log_exception_full(JSContext* cx, JS::HandleValue exc, JS::HandleString message, GLogLevelFlags level); +[[nodiscard]] std::string gjs_value_debug_string(JSContext* cx, + JS::HandleValue value); + void gjs_warning_reporter(JSContext*, JSErrorReport* report); GJS_JSAPI_RETURN_CONVENTION diff -Nru gjs-1.74.0/gjs/jsapi-util-root.h gjs-1.72.2/gjs/jsapi-util-root.h --- gjs-1.74.0/gjs/jsapi-util-root.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/jsapi-util-root.h 2022-08-08 05:05:12.000000000 +0000 @@ -62,9 +62,8 @@ template<> struct GjsHeapOperation { - [[nodiscard]] static bool update_after_gc(JSTracer* trc, - JS::Heap* location) { - JS_UpdateWeakPointerAfterGC(trc, location); + [[nodiscard]] static bool update_after_gc(JS::Heap* location) { + JS_UpdateWeakPointerAfterGC(location); return (location->unbarrieredGet() == nullptr); } @@ -179,7 +178,7 @@ void root(JSContext* cx, const T& thing) { debug("root()"); g_assert(!m_root); - g_assert(m_heap.get() == JS::SafelyInitialized::create()); + g_assert(m_heap.get() == JS::SafelyInitialized()); m_heap.~Heap(); m_root = std::make_unique>(cx, thing); } @@ -205,7 +204,7 @@ void reset() { debug("reset()"); if (!m_root) { - m_heap = JS::SafelyInitialized::create(); + m_heap = JS::SafelyInitialized(); return; } @@ -252,10 +251,10 @@ /* If not tracing, then you must call this method during GC in order to * update the object's location if it was moved, or null it out if it was * finalized. If the object was finalized, returns true. */ - bool update_after_gc(JSTracer* trc) { + bool update_after_gc() { debug("update_after_gc()"); g_assert(!m_root); - return GjsHeapOperation::update_after_gc(trc, &m_heap); + return GjsHeapOperation::update_after_gc(&m_heap); } [[nodiscard]] constexpr bool rooted() const { return m_root != nullptr; } diff -Nru gjs-1.74.0/gjs/jsapi-util-string.cpp gjs-1.72.2/gjs/jsapi-util-string.cpp --- gjs-1.74.0/gjs/jsapi-util-string.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/jsapi-util-string.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -32,7 +32,6 @@ #include // for JS_GetFunctionDisplayId #include // for IdToValue, IsFunctionObject, ... #include -#include #include "gjs/jsapi-util.h" #include "gjs/macros.h" @@ -438,7 +437,7 @@ return true; } - JSLinearString* lstr = id.toLinearString(); + JSLinearString* lstr = JSID_TO_LINEAR_STRING(id); JS::RootedString s(cx, JS_FORGET_STRING_LINEARNESS(lstr)); *name_p = JS_EncodeStringToUTF8(cx, s); return !!*name_p; @@ -475,7 +474,7 @@ { JS::RootedString str(cx, JS_AtomizeAndPinString(cx, string)); if (!str) - return JS::PropertyKey::Void(); + return JSID_VOID; return JS::PropertyKey::fromPinnedString(str); } @@ -662,6 +661,6 @@ gjs_debug_id(jsid id) { if (id.isString()) - return gjs_debug_linear_string(id.toLinearString(), NoQuotes); + return gjs_debug_linear_string(JSID_TO_LINEAR_STRING(id), NoQuotes); return gjs_debug_value(js::IdToValue(id)); } diff -Nru gjs-1.74.0/gjs/module.cpp gjs-1.72.2/gjs/module.cpp --- gjs-1.74.0/gjs/module.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/module.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -12,7 +12,6 @@ #include #include -#include #include #include // for ConstUTF8CharsZ #include @@ -22,24 +21,21 @@ #include // for JS_ReportOutOfMemory #include #include // for RootedVector -#include // for CurrentGlobalOrNull #include #include #include #include -#include #include #include #include -#include #include #include #include #include // for UniqueChars #include #include -#include // for JS_GetFunctionObject, JS_Ne... -#include // for NewFunctionWithReserved +#include // for JS_DefinePropertyById, ... +#include // for SetFunctionNativeReserved #include #include "gjs/atoms.h" @@ -47,7 +43,6 @@ #include "gjs/global.h" #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/mem-private.h" #include "gjs/module.h" #include "gjs/native.h" @@ -61,9 +56,6 @@ class GjsScriptModule { char *m_name; - // Reserved slots - static const size_t POINTER = 0; - GjsScriptModule(const char* name) { m_name = g_strdup(name); GJS_INC_COUNTER(module); @@ -80,15 +72,13 @@ /* Private data accessors */ [[nodiscard]] static inline GjsScriptModule* priv(JSObject* module) { - return JS::GetMaybePtrFromReservedSlot( - module, GjsScriptModule::POINTER); + return static_cast(JS::GetPrivate(module)); } /* Creates a JS module object. Use instead of the class's constructor */ [[nodiscard]] static JSObject* create(JSContext* cx, const char* name) { JSObject* module = JS_NewObject(cx, &GjsScriptModule::klass); - JS::SetReservedSlot(module, GjsScriptModule::POINTER, - JS::PrivateValue(new GjsScriptModule(name))); + JS::SetPrivate(module, new GjsScriptModule(name)); return module; } @@ -220,9 +210,7 @@ return priv(module)->resolve_impl(cx, module, id, resolved); } - static void finalize(JS::GCContext*, JSObject* module) { - delete priv(module); - } + static void finalize(JSFreeOp*, JSObject* module) { delete priv(module); } static constexpr JSClassOps class_ops = { nullptr, // addProperty @@ -236,7 +224,7 @@ static constexpr JSClass klass = { "GjsScriptModule", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &GjsScriptModule::class_ops, }; diff -Nru gjs-1.74.0/gjs/objectbox.cpp gjs-1.72.2/gjs/objectbox.cpp --- gjs-1.74.0/gjs/objectbox.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/objectbox.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -10,7 +10,6 @@ #include #include -#include // for JS_ReportOutOfMemory #include // for GCPolicy (ptr only), NonGCPointe... #include #include @@ -18,7 +17,6 @@ #include #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/objectbox.h" #include "util/log.h" diff -Nru gjs-1.74.0/gjs/profiler.cpp gjs-1.72.2/gjs/profiler.cpp --- gjs-1.74.0/gjs/profiler.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/profiler.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -16,6 +16,7 @@ # include # include // for sscanf # include // for memcpy, strlen +# include // for timer_t # include // for __NR_gettid # include // for size_t, CLOCK_MONOTONIC, itimerspec, ... # ifdef HAVE_UNISTD_H diff -Nru gjs-1.74.0/gjs/promise.cpp gjs-1.72.2/gjs/promise.cpp --- gjs-1.74.0/gjs/promise.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/promise.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -10,11 +10,10 @@ #include #include -#include // for JS_DefineFunctions #include #include #include -#include // for JS_NewPlainObject +#include // for JS_DefineFunctions, JS_NewPlainObject #include "gjs/context-private.h" #include "gjs/jsapi-util.h" diff -Nru gjs-1.74.0/gjs/text-encoding.cpp gjs-1.72.2/gjs/text-encoding.cpp --- gjs-1.74.0/gjs/text-encoding.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/text-encoding.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -5,46 +5,37 @@ #include -#include // for SSIZE_MAX -#include // for size_t #include #include // for strcmp, memchr, strlen #include -#include // for nullptr_t -#include // for distance -#include // for u16string #include #include +#include #include #include #include #include #include -#include // for JS_ReportOutOfMemory -#include // for JS_ClearPendingException, JS_... #include // for AutoCheckCannotGC -#include #include #include #include #include #include // for UniqueChars -#include #include -#include // for JS_NewPlainObject, JS_InstanceOf +#include // for JS_DefineFunctionById, JS_DefineFun... #include // for ProtoKeyToClass -#include // for JSProto_TypeError, JSProto_InternalError -#include -#include -#include #include +#include "gi/boxed.h" +#include "gjs/atoms.h" +#include "gjs/context-private.h" +#include "gjs/deprecation.h" #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/text-encoding.h" // Callback to use with JS::NewExternalArrayBuffer() diff -Nru gjs-1.74.0/gjs/text-encoding.h gjs-1.72.2/gjs/text-encoding.h --- gjs-1.74.0/gjs/text-encoding.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/gjs/text-encoding.h 2022-08-08 05:05:12.000000000 +0000 @@ -6,6 +6,10 @@ #include +#include // for size_t + +#include + #include #include "gjs/macros.h" diff -Nru gjs-1.74.0/installed-tests/debugger/keys.debugger.output gjs-1.72.2/installed-tests/debugger/keys.debugger.output --- gjs-1.74.0/installed-tests/debugger/keys.debugger.output 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/debugger/keys.debugger.output 2022-08-08 05:05:12.000000000 +0000 @@ -5,9 +5,17 @@ Debugger statement, toplevel at keys.debugger.js:8:0 db> keys a $1 = [object Array] -["foo", "bar", "tres"] +[ + "foo", + "bar", + "tres" +] db> k a $2 = [object Array] -["foo", "bar", "tres"] +[ + "foo", + "bar", + "tres" +] db> c Program exited with code 0 diff -Nru gjs-1.74.0/installed-tests/debugger/print.debugger gjs-1.72.2/installed-tests/debugger/print.debugger --- gjs-1.74.0/installed-tests/debugger/print.debugger 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/debugger/print.debugger 2022-08-08 05:05:12.000000000 +0000 @@ -20,5 +20,4 @@ p/b k p l p m -p n c diff -Nru gjs-1.74.0/installed-tests/debugger/print.debugger.js gjs-1.72.2/installed-tests/debugger/print.debugger.js --- gjs-1.74.0/installed-tests/debugger/print.debugger.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/debugger/print.debugger.js 2022-08-08 05:05:12.000000000 +0000 @@ -14,6 +14,5 @@ const k = class J {}; const l = new GObject.Object(); const m = new Error('message'); -const n = {a: 1}; debugger; -void (a, b, c, d, e, f, g, h, i, j, k, l, m, n); +void (a, b, c, d, e, f, g, h, i, j, k, l, m); diff -Nru gjs-1.74.0/installed-tests/debugger/print.debugger.output gjs-1.72.2/installed-tests/debugger/print.debugger.output --- gjs-1.74.0/installed-tests/debugger/print.debugger.output 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/debugger/print.debugger.output 2022-08-08 05:05:12.000000000 +0000 @@ -2,7 +2,7 @@ db> # SPDX-License-Identifier: MIT OR LGPL-2.0-or-later db> # SPDX-FileCopyrightText: 2018 Philip Chimento db> c -Debugger statement, toplevel at print.debugger.js:18:0 +Debugger statement, toplevel at print.debugger.js:17:0 db> # Simple types db> print a $1 = undefined @@ -21,36 +21,67 @@ db> # Objects db> print h $8 = [object Array] -[1, "money", 2, "show", { three: "to", get ready: "go cat go" }] +[ + 1, + "money", + 2, + "show", + { + "three": "to", + "get ready": "go cat go" + } +] db> print/b h $9 = [object Array] -[object Array] +{ + "0": 1, + "1": "money", + "2": 2, + "3": "show", + "4": "(...)", + "length": 5 +} db> print/p h $10 = [object Array] -[1, "money", 2, "show", { three: "to", get ready: "go cat go" }] +[ + 1, + "money", + 2, + "show", + { + "three": "to", + "get ready": "go cat go" + } +] db> p i $11 = [object Object] -{ some: "plain object", that: "has keys" } +{ + "some": "plain object", + "that": "has keys" +} db> p/b i $12 = [object Object] -[object Object] +{ + "some": "plain object", + "that": "has keys" +} db> p j $13 = [object Set] {} db> p k $14 = [object Function] -[ Function: J ] db> p/b k $15 = [object Function] -[object Function] +{ + "prototype": "(...)", + "length": 0, + "name": "J" +} db> p l $16 = [object GObject_Object] [object instance wrapper GIName:GObject.Object jsobj@0xADDR native@0xADDR] db> p m $17 = [object Error] Error: message -db> p n -$18 = [object Object] -{ a: 1 } db> c Program exited with code 0 diff -Nru gjs-1.74.0/installed-tests/js/minijasmine.js gjs-1.72.2/installed-tests/js/minijasmine.js --- gjs-1.74.0/installed-tests/js/minijasmine.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/js/minijasmine.js 2022-08-08 05:05:12.000000000 +0000 @@ -4,6 +4,11 @@ const GLib = imports.gi.GLib; +function _removeNewlines(str) { + let allNewlines = /\n/g; + return str.replace(allNewlines, '\\n'); +} + function _filterStack(stack) { if (!stack) return 'No stack'; @@ -22,7 +27,6 @@ }); globalThis._jasmineMain = GLib.MainLoop.new(null, false); globalThis._jasmineRetval = 0; -globalThis._jasmineErrorsOutput = []; // Install Jasmine API on the global object let jasmineInterface = jasmineRequire.interface(jasmineCore, globalThis._jasmineEnv); @@ -74,8 +78,7 @@ tapReport = 'ok'; } tapReport += ` ${this._specCount} ${result.fullName}`; - if (result.status === 'pending' || result.status === 'disabled' || - result.status === 'excluded') { + if (result.status === 'pending' || result.status === 'disabled') { let reason = result.pendingReason || result.status; tapReport += ` # SKIP ${reason}`; } @@ -84,22 +87,10 @@ // Print additional diagnostic info on failure if (result.status === 'failed' && result.failedExpectations) { result.failedExpectations.forEach(failedExpectation => { - const output = []; - const messageLines = failedExpectation.message.split('\n'); - output.push(`Message: ${messageLines.shift()}`); - output.push(...messageLines.map(str => ` ${str}`)); - output.push('Stack:'); + print('# Message:', _removeNewlines(failedExpectation.message)); + print('# Stack:'); let stackTrace = _filterStack(failedExpectation.stack).trim(); - output.push(...stackTrace.split('\n').map(str => ` ${str}`)); - - if (globalThis._jasmineErrorsOutput.length) { - globalThis._jasmineErrorsOutput.push( - Array(GLib.getenv('COLUMNS') || 80).fill('―').join('')); - } - - globalThis._jasmineErrorsOutput.push(`Test: ${result.fullName}`); - globalThis._jasmineErrorsOutput.push(...output); - print(output.map(l => `# ${l}`).join('\n')); + print(stackTrace.split('\n').map(str => `# ${str}`).join('\n')); }); } } diff -Nru gjs-1.74.0/installed-tests/js/testGDBus.js gjs-1.72.2/installed-tests/js/testGDBus.js --- gjs-1.74.0/installed-tests/js/testGDBus.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/js/testGDBus.js 2022-08-08 05:05:12.000000000 +0000 @@ -330,11 +330,6 @@ loop.run(); }); - it('can call a method with async/await', async function () { - const [{hello}] = await proxy.frobateStuffAsync({}); - expect(hello.deepUnpack()).toEqual('world'); - }); - it('can call a remote method when not using makeProxyWrapper', function () { let info = Gio.DBusNodeInfo.new_for_xml(TestIface); let iface = info.interfaces[0]; @@ -373,13 +368,6 @@ loop.run(); }); - it('can handle an exception thrown by a method with async/await', async function () { - GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING, - 'JS ERROR: Exception in method call: alwaysThrowException: *'); - - await expectAsync(proxy.alwaysThrowExceptionAsync({})).toBeRejected(); - }); - it('can still destructure the return value when an exception is thrown', function () { GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING, 'JS ERROR: Exception in method call: alwaysThrowException: *'); @@ -410,11 +398,6 @@ loop.run(); }); - it('throws an exception when trying to call an async method that does not exist', async function () { - delete Test.prototype.thisDoesNotExist; - await expectAsync(proxy.thisDoesNotExistAsync()).toBeRejected(); - }); - it('can pass a parameter to a remote method that is not a JSON object', function () { proxy.nonJsonFrobateStuffRemote(42, ([result], excp) => { expect(result).toEqual('42 it is!'); @@ -424,11 +407,6 @@ loop.run(); }); - it('can pass a parameter to a method with async/await that is not a JSON object', async function () { - const [result] = await proxy.nonJsonFrobateStuffAsync(1); - expect(result).toEqual('Oops'); - }); - it('can call a remote method with no in parameter', function () { proxy.noInParameterRemote(([result], excp) => { expect(result).toEqual('Yes!'); @@ -438,11 +416,6 @@ loop.run(); }); - it('can call an async/await method with no in parameter', async function () { - const [result] = await proxy.noInParameterAsync(); - expect(result).toEqual('Yes!'); - }); - it('can call a remote method with multiple in parameters', function () { proxy.multipleInArgsRemote(1, 2, 3, 4, 5, ([result], excp) => { expect(result).toEqual('1 2 3 4 5'); @@ -452,11 +425,6 @@ loop.run(); }); - it('can call an async/await method with multiple in parameters', async function () { - const [result] = await proxy.multipleInArgsAsync(1, 2, 3, 4, 5); - expect(result).toEqual('1 2 3 4 5'); - }); - it('can call a remote method with no return value', function () { proxy.noReturnValueRemote(([result], excp) => { expect(result).not.toBeDefined(); @@ -466,11 +434,6 @@ loop.run(); }); - it('can call an async/await method with no return value', async function () { - const [result] = await proxy.noReturnValueAsync(); - expect(result).not.toBeDefined(); - }); - it('can emit a DBus signal', function () { let handler = jasmine.createSpy('signalFoo'); let id = proxy.connectSignal('signalFoo', handler); @@ -487,18 +450,6 @@ loop.run(); }); - it('can emit a DBus signal with async/await', async function () { - const handler = jasmine.createSpy('signalFoo'); - const id = proxy.connectSignal('signalFoo', handler); - handler.and.callFake(() => proxy.disconnectSignal(id)); - - const [result] = await proxy.emitSignalAsync(); - expect(result).not.toBeDefined(); - expect(handler).toHaveBeenCalledTimes(1); - expect(handler).toHaveBeenCalledWith(jasmine.anything(), - jasmine.anything(), ['foobar']); - }); - it('can call a remote method with multiple return values', function () { proxy.multipleOutValuesRemote(function (result, excp) { expect(result).toEqual(['Hello', 'World', '!']); @@ -508,11 +459,6 @@ loop.run(); }); - it('can call an async/await method with multiple return values', async function () { - const results = await proxy.multipleOutValuesAsync(); - expect(results).toEqual(['Hello', 'World', '!']); - }); - it('does not coalesce one array into the array of return values', function () { proxy.oneArrayOutRemote(([result], excp) => { expect(result).toEqual(['Hello', 'World', '!']); @@ -522,11 +468,6 @@ loop.run(); }); - it('does not coalesce one array into the array of return values with async/await', async function () { - const [result] = await proxy.oneArrayOutAsync(); - expect(result).toEqual(['Hello', 'World', '!']); - }); - it('does not coalesce an array of arrays into the array of return values', function () { proxy.arrayOfArrayOutRemote(([[a1, a2]], excp) => { expect(a1).toEqual(['Hello', 'World']); @@ -537,12 +478,6 @@ loop.run(); }); - it('does not coalesce an array of arrays into the array of return values with async/await', async function () { - const [[a1, a2]] = await proxy.arrayOfArrayOutAsync(); - expect(a1).toEqual(['Hello', 'World']); - expect(a2).toEqual(['World', 'Hello']); - }); - it('can return multiple arrays from a remote method', function () { proxy.multipleArrayOutRemote(([a1, a2], excp) => { expect(a1).toEqual(['Hello', 'World']); @@ -553,12 +488,6 @@ loop.run(); }); - it('can return multiple arrays from an async/await method', async function () { - const [a1, a2] = await proxy.multipleArrayOutAsync(); - expect(a1).toEqual(['Hello', 'World']); - expect(a2).toEqual(['World', 'Hello']); - }); - it('handles a bad signature by throwing an exception', function () { proxy.arrayOutBadSigRemote(function (result, excp) { expect(excp).not.toBeNull(); @@ -567,10 +496,6 @@ loop.run(); }); - it('handles a bad signature in async/await by rejecting the promise', async function () { - await expectAsync(proxy.arrayOutBadSigAsync()).toBeRejected(); - }); - it('can call a remote method that is implemented asynchronously', function () { let someString = 'Hello world!'; let someInt = 42; @@ -584,14 +509,6 @@ loop.run(); }); - it('can call an async/await method that is implemented asynchronously', async function () { - const someString = 'Hello world!'; - const someInt = 42; - - const results = await proxy.echoAsync(someString, someInt); - expect(results).toEqual([someString, someInt]); - }); - it('can send and receive bytes from a remote method', function () { let someBytes = [0, 63, 234]; someBytes.forEach(b => { @@ -605,14 +522,6 @@ }); }); - it('can send and receive bytes from an async/await method', async function () { - let someBytes = [0, 63, 234]; - await Promise.allSettled(someBytes.map(async b => { - const [byte] = await proxy.byteEchoAsync(b); - expect(byte).toEqual(b); - })); - }); - it('can call a remote method that returns an array of structs', function () { proxy.structArrayRemote(([result], excp) => { expect(excp).toBeNull(); @@ -622,11 +531,6 @@ loop.run(); }); - it('can call an async/await method that returns an array of structs', async function () { - const [result] = await proxy.structArrayAsync(); - expect(result).toEqual([[128, 123456], [42, 654321]]); - }); - it('can send and receive dicts from a remote method', function () { let someDict = { aDouble: new GLib.Variant('d', 10), @@ -654,19 +558,6 @@ loop.run(); }); - it('can send and receive dicts from an async/await method', async function () { - // See notes in test above - const [result] = await proxy.dictEchoAsync({ - aDouble: new GLib.Variant('d', 10), - anInteger: new GLib.Variant('i', 10.5), - aDoubleBeforeAndAfter: new GLib.Variant('d', 10.5), - }); - expect(result).not.toBeNull(); - expect(result['anInteger'].deepUnpack()).toEqual(10); - expect(result['aDoubleBeforeAndAfter'].deepUnpack()).toEqual(10.5); - expect(result['aDouble'].deepUnpack()).toBe(10.0); - }); - it('can call a remote method with a Unix FD', function (done) { const expectedBytes = ByteArray.fromString('some bytes'); const fd = GjsTestTools.open_bytes(expectedBytes); @@ -679,16 +570,6 @@ }); }); - it('can call an async/await method with a Unix FD', async function () { - const encoder = new TextEncoder(); - const expectedBytes = encoder.encode('some bytes'); - const fd = GjsTestTools.open_bytes(expectedBytes); - const fdList = Gio.UnixFDList.new_from_array([fd]); - const [bytes, outFdList] = await proxy.fdInAsync(0, fdList); - expect(outFdList).not.toBeDefined(); - expect(bytes).toEqual(expectedBytes); - }); - it('can call an asynchronously implemented remote method with a Unix FD', function (done) { const expectedBytes = ByteArray.fromString('some bytes'); const fd = GjsTestTools.open_bytes(expectedBytes); @@ -701,16 +582,6 @@ }); }); - it('can call an asynchronously implemented async/await method with a Unix FD', async function () { - const encoder = new TextEncoder(); - const expectedBytes = encoder.encode('some bytes'); - const fd = GjsTestTools.open_bytes(expectedBytes); - const fdList = Gio.UnixFDList.new_from_array([fd]); - const [bytes, outFdList] = await proxy.fdIn2Async(0, fdList); - expect(outFdList).not.toBeDefined(); - expect(bytes).toEqual(expectedBytes); - }); - function readBytesFromFdSync(fd) { const stream = new Gio.UnixInputStream({fd, closeFd: true}); const bytes = stream.read_bytes(4096, null); @@ -727,14 +598,6 @@ }); }); - it('can call an async/await method that returns a Unix FD', async function () { - const encoder = new TextEncoder(); - const expectedBytes = encoder.encode('some bytes'); - const [fdIndex, outFdList] = await proxy.fdOutAsync(expectedBytes); - const bytes = readBytesFromFdSync(outFdList.get(fdIndex)); - expect(bytes).toEqual(expectedBytes); - }); - it('can call an asynchronously implemented remote method that returns a Unix FD', function (done) { const expectedBytes = ByteArray.fromString('some bytes'); proxy.fdOut2Remote(expectedBytes, ([fdIndex], exc, outFdList) => { @@ -745,32 +608,15 @@ }); }); - it('can call an asynchronously implemented asyc/await method that returns a Unix FD', async function () { - const encoder = new TextEncoder(); - const expectedBytes = encoder.encode('some bytes'); - const [fdIndex, outFdList] = await proxy.fdOut2Async(expectedBytes); - const bytes = readBytesFromFdSync(outFdList.get(fdIndex)); - expect(bytes).toEqual(expectedBytes); - }); - it('throws an exception when not passing a Gio.UnixFDList to a method that requires one', function () { expect(() => proxy.fdInRemote(0, () => {})).toThrow(); }); - it('rejects the promise when not passing a Gio.UnixFDList to an async method that requires one', async function () { - await expectAsync(proxy.fdInAsync(0)).toBeRejected(); - }); - it('throws an exception when passing a handle out of range of a Gio.UnixFDList', function () { const fdList = new Gio.UnixFDList(); expect(() => proxy.fdInRemote(0, fdList, () => {})).toThrow(); }); - it('rejects the promise when async passing a handle out of range of a Gio.UnixFDList', async function () { - const fdList = new Gio.UnixFDList(); - await expectAsync(proxy.fdInAsync(0, fdList)).toBeRejected(); - }); - it('Has defined properties', function () { expect(proxy.hasOwnProperty('PropReadWrite')).toBeTruthy(); expect(proxy.hasOwnProperty('PropReadOnly')).toBeTruthy(); diff -Nru gjs-1.74.0/installed-tests/js/testGio.js gjs-1.72.2/installed-tests/js/testGio.js --- gjs-1.74.0/installed-tests/js/testGio.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/js/testGio.js 2022-08-08 05:05:12.000000000 +0000 @@ -72,27 +72,6 @@ expect(() => Gio._promisify(Gio.Subprocess.prototype, 'communicate_utf8_async', 'commuicate_utf8_finish')).toThrowError(/commuicate_utf8_finish/); }); - it('promisifies functions', async function () { - Gio._promisify(Gio.File.prototype, 'query_info_async'); - const file = Gio.File.new_for_path('.'); - - const fileInfo = await file.query_info_async(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, - Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_DEFAULT, null); - expect(fileInfo.get_file_type()).not.toBe(Gio.FileType.UNKNOWN); - }); - - it('preserves old behavior', function (done) { - Gio._promisify(Gio.File.prototype, 'query_info_async'); - const file = Gio.File.new_for_path('.'); - - file.query_info_async(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, - Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_DEFAULT, null, (_, res) => { - const fileInfo = file.query_info_finish(res); - expect(fileInfo.get_file_type()).not.toBe(Gio.FileType.UNKNOWN); - done(); - }); - }); - it('can guess the finish function', function () { expect(() => Gio._promisify(Gio._LocalFilePrototype, 'read_async')).not.toThrow(); expect(() => Gio._promisify(Gio.DBus, 'get')).not.toThrow(); @@ -218,205 +197,3 @@ }); }); }); - -describe('Gio.add_action_entries override', function () { - it('registers each entry as an action', function () { - const app = new Gio.Application(); - - const entries = [ - { - name: 'foo', - parameter_type: 's', - }, - { - name: 'bar', - state: 'false', - }, - ]; - - app.add_action_entries(entries); - - expect(app.lookup_action('foo').name).toEqual(entries[0].name); - expect(app.lookup_action('foo').parameter_type.dup_string()).toEqual(entries[0].parameter_type); - - expect(app.lookup_action('bar').name).toEqual(entries[1].name); - expect(app.lookup_action('bar').state.print(true)).toEqual(entries[1].state); - }); - - it('connects and binds the activate handler', function (done) { - const app = new Gio.Application(); - let action; - - const entries = [ - { - name: 'foo', - parameter_type: 's', - activate() { - expect(this).toBe(action); - done(); - }, - }, - ]; - - app.add_action_entries(entries); - action = app.lookup_action('foo'); - - action.activate(new GLib.Variant('s', 'hello')); - }); - - it('connects and binds the change_state handler', function (done) { - const app = new Gio.Application(); - let action; - - const entries = [ - { - name: 'bar', - state: 'false', - change_state() { - expect(this).toBe(action); - done(); - }, - }, - ]; - - app.add_action_entries(entries); - action = app.lookup_action('bar'); - - action.change_state(new GLib.Variant('b', 'true')); - }); - - it('throw an error if the parameter_type is invalid', function () { - const app = new Gio.Application(); - - const entries = [ - { - name: 'foo', - parameter_type: '(((', - }, - ]; - - expect(() => app.add_action_entries(entries)).toThrow(); - }); - - it('throw an error if the state is invalid', function () { - const app = new Gio.Application(); - - const entries = [ - { - name: 'bar', - state: 'foo', - }, - ]; - - expect(() => app.add_action_entries(entries)).toThrow(); - }); -}); - -describe('Gio.FileEnumerator overrides', function () { - it('iterates synchronously', function () { - const dir = Gio.File.new_for_path('.'); - let count = 0; - for (const value of dir.enumerate_children( - 'standard::name', - Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - null - )) { - expect(value).toBeInstanceOf(Gio.FileInfo); - count++; - } - expect(count).toBeGreaterThan(0); - }); - - it('iterates asynchronously', async function () { - const dir = Gio.File.new_for_path('.'); - let count = 0; - for await (const value of dir.enumerate_children( - 'standard::name', - Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - null - )) { - expect(value).toBeInstanceOf(Gio.FileInfo); - count++; - } - expect(count).toBeGreaterThan(0); - }); -}); - -describe('Non-introspectable file attribute overrides', function () { - let numExpectedWarnings, file, info; - const flags = [Gio.FileQueryInfoFlags.NONE, null]; - - function expectWarnings(count) { - numExpectedWarnings = count; - for (let c = 0; c < count; c++) { - GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING, - '*not introspectable*'); - } - } - - function assertWarnings(testName) { - for (let c = 0; c < numExpectedWarnings; c++) { - GLib.test_assert_expected_messages_internal('Gjs', 'testGio.js', 0, - `test Gio.${testName}`); - } - numExpectedWarnings = 0; - } - - beforeEach(function () { - numExpectedWarnings = 0; - [file] = Gio.File.new_tmp('XXXXXX'); - info = file.query_info('standard::*', ...flags); - }); - - it('invalid means unsetting the attribute', function () { - expectWarnings(2); - expect(() => - file.set_attribute('custom::remove', Gio.FileAttributeType.INVALID, null, ...flags)) - .toThrowError(/not introspectable/); - expect(() => info.set_attribute('custom::remove', Gio.FileAttributeType.INVALID)).not.toThrow(); - assertWarnings(); - }); - - it('works for boolean', function () { - expectWarnings(2); - expect(() => - file.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN, Gio.FileAttributeType.BOOLEAN, false, ...flags)) - .toThrowError(/not introspectable/); - expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN, Gio.FileAttributeType.BOOLEAN, false)) - .not.toThrow(); - assertWarnings(); - }); - - it('works for uint32', function () { - expectWarnings(2); - expect(() => file.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED_USEC, Gio.FileAttributeType.UINT32, 123456, ...flags)) - .not.toThrow(); - expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED_USEC, Gio.FileAttributeType.UINT32, 654321)) - .not.toThrow(); - assertWarnings(); - }); - - it('works for uint64', function () { - expectWarnings(2); - expect(() => file.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED, Gio.FileAttributeType.UINT64, Date.now() / 1000, ...flags)) - .not.toThrow(); - expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_TIME_MODIFIED, Gio.FileAttributeType.UINT64, Date.now() / 1000)) - .not.toThrow(); - assertWarnings(); - }); - - it('works for object', function () { - expectWarnings(2); - const icon = Gio.ThemedIcon.new_from_names(['list-add-symbolic']); - expect(() => - file.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileAttributeType.OBJECT, icon, ...flags)) - .toThrowError(/not introspectable/); - expect(() => info.set_attribute(Gio.FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileAttributeType.OBJECT, icon)) - .not.toThrow(); - assertWarnings(); - }); - - afterEach(function () { - file.delete_async(GLib.PRIORITY_DEFAULT, null, (obj, res) => obj.delete_finish(res)); - }); -}); diff -Nru gjs-1.74.0/installed-tests/js/testGObjectClass.js gjs-1.72.2/installed-tests/js/testGObjectClass.js --- gjs-1.74.0/installed-tests/js/testGObjectClass.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/js/testGObjectClass.js 2022-08-08 05:05:12.000000000 +0000 @@ -1164,24 +1164,6 @@ expect(a.bool).toEqual(true); expect(b.string).toEqual('true'); }); - - it('can be set up as a group', function () { - const group = new GObject.BindingGroup({source: a}); - group.bind('string', b, 'string', GObject.BindingFlags.NONE); - a.string = 'foo'; - expect(a.string).toEqual('foo'); - expect(b.string).toEqual('foo'); - }); - - it('can be set up as a group with custom mappings', function () { - const group = new GObject.BindingGroup({source: a}); - group.bind_full('bool', b, 'string', GObject.BindingFlags.NONE, - (bind, source) => [true, `${source}`], - null); - a.bool = true; - expect(a.bool).toEqual(true); - expect(b.string).toEqual('true'); - }); }); describe('Auto accessor generation', function () { @@ -1201,11 +1183,6 @@ 'Construct-only property with a setter method', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, 0, 100, 80), - 'construct-only-was-invalid-in-turkish': GObject.ParamSpec.int( - 'construct-only-was-invalid-in-turkish', 'Camel name in Turkish', - 'Camel-cased property that was wrongly transformed in Turkish', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - 0, 100, 55), 'snake-name': GObject.ParamSpec.int('snake-name', 'Snake name', 'Snake-cased property', GObject.ParamFlags.READWRITE, 0, 100, 36), 'camel-name': GObject.ParamSpec.int('camel-name', 'Camel name', @@ -1325,21 +1302,6 @@ expect(a._constructOnlySetterCalled).toEqual(1); }); - it('set properties at construct time with locale', function () { - const {gettext: Gettext} = imports; - const prevLocale = Gettext.setlocale(Gettext.LocaleCategory.ALL, null); - - Gettext.setlocale(Gettext.LocaleCategory.ALL, 'tr_TR'); - a = new AutoAccessors({ - 'construct-only-was-invalid-in-turkish': 35, - }); - Gettext.setlocale(Gettext.LocaleCategory.ALL, prevLocale); - - expect(a.constructOnlyWasInvalidInTurkish).toEqual(35); - expect(a.construct_only_was_invalid_in_turkish).toEqual(35); - expect(a['construct-only-was-invalid-in-turkish']).toEqual(35); - }); - it('notify when the property changes', function () { const notify = jasmine.createSpy('notify'); a.connect('notify::simple', notify); diff -Nru gjs-1.74.0/installed-tests/js/testPrint.js gjs-1.72.2/installed-tests/js/testPrint.js --- gjs-1.74.0/installed-tests/js/testPrint.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/js/testPrint.js 2022-08-08 05:05:12.000000000 +0000 @@ -1,11 +1,5 @@ // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later // SPDX-FileCopyrightText: 2020 Philip Chimento -// SPDX-FileCopyrightText: 2022 Nasah Kuma - -imports.gi.versions.Gdk = '3.0'; -const Gdk = imports.gi.Gdk; -const {getPrettyPrintFunction} = imports._print; -let prettyPrint = getPrettyPrintFunction(globalThis); describe('print', function () { it('can be spied upon', function () { @@ -38,118 +32,3 @@ expect(logError).toHaveBeenCalledWith('foo', 'bar'); }); }); - -describe('prettyPrint', function () { - it('property value primitive', function () { - expect( - prettyPrint({greeting: 'hi'}) - ).toBe('{ greeting: "hi" }'); - }); - - it('property value is object reference', function () { - let obj = {a: 5}; - obj.b = obj; - expect( - prettyPrint(obj) - ).toBe('{ a: 5, b: [Circular] }'); - }); - - it('more than one property', function () { - expect( - prettyPrint({a: 1, b: 2, c: 3}) - ).toBe('{ a: 1, b: 2, c: 3 }'); - }); - - it('add property value after property value object reference', function () { - let obj = {a: 5}; - obj.b = obj; - obj.c = 4; - expect( - prettyPrint(obj) - ).toBe('{ a: 5, b: [Circular], c: 4 }'); - }); - - it('array', function () { - expect( - prettyPrint([1, 2, 3, 4, 5]) - ).toBe('[1, 2, 3, 4, 5]'); - }); - - it('property value array', function () { - expect( - prettyPrint({arr: [1, 2, 3, 4, 5]}) - ).toBe('{ arr: [1, 2, 3, 4, 5] }'); - }); - - it('array reference is the only array element', function () { - let arr = []; - arr.push(arr); - expect( - prettyPrint(arr) - ).toBe('[[Circular]]'); - }); - - it('array reference is one of multiple array elements', function () { - let arr = []; - arr.push(4); - arr.push(arr); - arr.push(5); - expect( - prettyPrint(arr) - ).toBe('[4, [Circular], 5]'); - }); - - it('nested array', function () { - expect( - prettyPrint([1, 2, [3, 4], 5]) - ).toBe('[1, 2, [3, 4], 5]'); - }); - - it('property value nested array', function () { - expect( - prettyPrint({arr: [1, 2, [3, 4], 5]}) - ).toBe('{ arr: [1, 2, [3, 4], 5] }'); - }); - - it('function', function () { - expect( - prettyPrint(function sum(a, b) { - return a + b; - }) - ).toBe('[ Function: sum ]'); - }); - - it('property value function', function () { - expect( - prettyPrint({ - sum: function sum(a, b) { - return a + b; - }, - }) - ).toBe('{ sum: [ Function: sum ] }'); - }); - - it('date', function () { - expect( - prettyPrint(new Date(Date.UTC(2018, 11, 24, 10, 33, 30))) - ).toBe('2018-12-24T10:33:30.000Z'); - }); - - it('property value date', function () { - expect( - prettyPrint({date: new Date(Date.UTC(2018, 11, 24, 10, 33, 30))}) - ).toBe('{ date: 2018-12-24T10:33:30.000Z }'); - }); - - it('toString is overridden on object', function () { - expect( - prettyPrint(new Gdk.Rectangle()) - ).toMatch(/\[boxed instance wrapper GIName:.*\]/); - }); - - it('string tag supplied', function () { - expect( - prettyPrint(Gdk) - ).toMatch('[object GIRepositoryNamespace]'); - }); -}); diff -Nru gjs-1.74.0/installed-tests/minijasmine.cpp gjs-1.72.2/installed-tests/minijasmine.cpp --- gjs-1.74.0/installed-tests/minijasmine.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/minijasmine.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -104,18 +104,8 @@ if (!success) bail_out(cx, error->message); - if (code != 0) { - success = gjs_context_eval(cx, R"js( - printerr(globalThis._jasmineErrorsOutput.join('\n')); - )js", - -1, "", &code, &error); - - if (!success) - bail_out(cx, error->message); - - if (code != 0) - g_print("# Test script failed; see test log for assertions\n"); - } + if (code != 0) + g_print("# Test script failed; see test log for assertions\n"); if (coverage) { gjs_coverage_write_statistics(coverage); diff -Nru gjs-1.74.0/installed-tests/scripts/testExamples.sh gjs-1.72.2/installed-tests/scripts/testExamples.sh --- gjs-1.74.0/installed-tests/scripts/testExamples.sh 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/installed-tests/scripts/testExamples.sh 2022-08-08 05:05:12.000000000 +0000 @@ -6,26 +6,26 @@ source "${DIR}"/common.sh # Run the examples -$gjs -m examples/gio-cat.js meson.build +$gjs examples/gio-cat.js meson.build report "run the gio-cat.js example" if [[ -n "${ENABLE_GTK}" ]]; then export graphical_gjs="xvfb-run -a dbus-run-session -- $gjs" - eval timeout 5s $graphical_gjs -m examples/calc.js + eval timeout 5s $graphical_gjs examples/calc.js report_timeout "run the calc.js example" - eval timeout 5s $graphical_gjs -m examples/gtk3.js - report_timeout "run the gtk3.js example" + eval timeout 5s $graphical_gjs examples/gtk.js + report_timeout "run the gtk.js example" - eval timeout 5s $graphical_gjs -m examples/gtk-application.js + eval timeout 5s $graphical_gjs examples/gtk-application.js report_timeout "run the gtk-application.js example" - eval timeout 5s $graphical_gjs -m examples/gettext.js + eval timeout 5s $graphical_gjs examples/gettext.js report_timeout "run the gettext.js example" else skip "run the calc.js example" "running without GTK" - skip "run the gtk3.js example" "running without GTK" + skip "run the gtk.js example" "running without GTK" skip "run the gtk-application.js example" "running without GTK" skip "run the gettext.js example" "running without GTK" fi diff -Nru gjs-1.74.0/libgjs-private/gjs-util.c gjs-1.72.2/libgjs-private/gjs-util.c --- gjs-1.74.0/libgjs-private/gjs-util.c 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/libgjs-private/gjs-util.c 2022-08-08 05:05:12.000000000 +0000 @@ -125,28 +125,6 @@ to_closure, from_closure); } -void gjs_g_binding_group_bind_full( - GBindingGroup* source, const char* source_property, GObject* target, - const char* target_property, GBindingFlags flags, - GjsBindingTransformFunc to_callback, void* to_data, - GDestroyNotify to_notify, GjsBindingTransformFunc from_callback, - void* from_data, GDestroyNotify from_notify) { - GClosure* to_closure = NULL; - GClosure* from_closure = NULL; - - if (to_callback) - to_closure = g_cclosure_new(G_CALLBACK(to_callback), to_data, - G_CLOSURE_NOTIFY(to_notify)); - - if (from_callback) - from_closure = g_cclosure_new(G_CALLBACK(from_callback), from_data, - G_CLOSURE_NOTIFY(from_notify)); - - g_binding_group_bind_with_closures(source, source_property, target, - target_property, flags, - to_closure, from_closure); -} - #undef G_CLOSURE_NOTIFY static GParamSpec* gjs_gtk_container_class_find_child_property( @@ -340,19 +318,11 @@ static void* log_writer_user_data = NULL; static GDestroyNotify log_writer_user_data_free = NULL; -static GThread* log_writer_thread = NULL; static GLogWriterOutput gjs_log_writer_func_wrapper(GLogLevelFlags log_level, const GLogField* fields, size_t n_fields, void* user_data) { - g_assert(log_writer_thread); - - // If the wrapper is called from a thread other than the one that set it, - // return unhandled so the fallback logger is used. - if (g_thread_self() != log_writer_thread) - return g_log_writer_default(log_level, fields, n_fields, NULL); - GjsGLogWriterFunc func = (GjsGLogWriterFunc)user_data; GVariantDict dict; g_variant_dict_init(&dict, NULL); @@ -393,12 +363,6 @@ func(log_level, string_fields, log_writer_user_data); g_variant_unref(string_fields); - - // If the function did not handle the log, fallback to the default - // handler. - if (output == G_LOG_WRITER_UNHANDLED) - return g_log_writer_default(log_level, fields, n_fields, NULL); - return output; } @@ -415,7 +379,6 @@ g_log_set_writer_func(g_log_writer_default, NULL, NULL); log_writer_user_data_free = NULL; log_writer_user_data = NULL; - log_writer_thread = NULL; } /** @@ -432,7 +395,6 @@ GDestroyNotify user_data_free) { log_writer_user_data = user_data; log_writer_user_data_free = user_data_free; - log_writer_thread = g_thread_self(); g_log_set_writer_func(gjs_log_writer_func_wrapper, func, NULL); } diff -Nru gjs-1.74.0/libgjs-private/gjs-util.h gjs-1.72.2/libgjs-private/gjs-util.h --- gjs-1.74.0/libgjs-private/gjs-util.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/libgjs-private/gjs-util.h 2022-08-08 05:05:12.000000000 +0000 @@ -141,28 +141,6 @@ GDestroyNotify to_notify, GjsBindingTransformFunc from_callback, void* from_data, GDestroyNotify from_notify); -/** - * gjs_g_binding_group_bind_full: - * @source: - * @source_property: - * @target: - * @target_property: - * @flags: - * @to_callback: (scope notified) (nullable): - * @to_data: (closure to_callback): - * @to_notify: (destroy to_data): - * @from_callback: (scope notified) (nullable): - * @from_data: (closure from_callback): - * @from_notify: (destroy from_data): - */ -GJS_EXPORT -void gjs_g_binding_group_bind_full( - GBindingGroup* source, const char* source_property, GObject* target, - const char* target_property, GBindingFlags flags, - GjsBindingTransformFunc to_callback, void* to_data, - GDestroyNotify to_notify, GjsBindingTransformFunc from_callback, - void* from_data, GDestroyNotify from_notify); - /* For imports.overrides.Gtk */ GJS_EXPORT void gjs_gtk_container_child_set_property(GObject* container, GObject* child, diff -Nru gjs-1.74.0/meson.build gjs-1.72.2/meson.build --- gjs-1.74.0/meson.build 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/meson.build 2022-08-08 05:05:12.000000000 +0000 @@ -2,8 +2,8 @@ # SPDX-FileCopyrightText: 2019 Philip Chimento # SPDX-FileCopyrightText: 2019 Chun-wei Fan -project('gjs', 'cpp', 'c', version: '1.74.0', license: ['MIT', 'LGPL2+'], - meson_version: '>= 0.54.0', +project('gjs', 'cpp', 'c', version: '1.72.2', license: ['MIT', 'LGPL2+'], + meson_version: '>= 0.52.0', default_options: ['cpp_std=c++17', 'cpp_rtti=false', 'c_std=c99', 'warning_level=2', 'b_pch=true' ]) @@ -14,7 +14,6 @@ api_version = '1.0' api_name = '@0@-@1@'.format(meson.project_name(), api_version) -fs = import('fs') gnome = import('gnome') pkg = import('pkgconfig') @@ -40,7 +39,6 @@ add_project_arguments(cxx.get_supported_arguments([ '-utf-8', # Use UTF-8 mode '/Zc:externConstexpr', # Required for 'extern constexpr' on MSVC - '/Zc:preprocessor', # Required to consume the mozjs-102 headers on MSVC # Ignore spurious compiler warnings for things that GLib and SpiderMonkey # header files commonly do @@ -128,7 +126,7 @@ ffi = dependency('libffi', fallback: ['libffi', 'ffi_dep']) gi = dependency('gobject-introspection-1.0', version: '>= 1.66.0', fallback: ['gobject-introspection', 'girepo_dep']) -spidermonkey = dependency('mozjs-102') +spidermonkey = dependency('mozjs-91', version: '>= 91.3.0') # We might need to look for the headers and lib's for Cairo # manually on MSVC/clang-cl builds... @@ -149,13 +147,12 @@ required: get_option('profiler'), include_type: 'system', fallback: ['sysprof', 'libsysprof_capture_dep'], default_options: [ - 'agent=false', - 'examples=false', - 'gtk=false', - 'tests=false', - 'tools=false', + 'enable_examples=false', + 'enable_gtk=false', + 'enable_tests=false', + 'enable_tools=false', 'libsysprof=false', - 'sysprofd=none', + 'with_sysprofd=none', 'help=false', ]) @@ -710,9 +707,6 @@ '--error-exitcode=1' ] -add_test_setup('quiet', env: ['GJS_DEBUG_TOPICS='], is_default: true) -add_test_setup('verbose') - add_test_setup('valgrind', timeout_multiplier: 40, env: valgrind_environment, exe_wrapper: ['valgrind'] + valgrind_args) @@ -762,52 +756,12 @@ ### Summarize options ########################################################## -prefix = get_option('prefix') -bindir = get_option('bindir') -libdir = get_option('libdir') -datadir = get_option('datadir') -summary({ - 'prefix': prefix, - 'bindir': fs.is_absolute(bindir) ? bindir : prefix / bindir, - 'libdir': fs.is_absolute(libdir) ? libdir : prefix / libdir, - 'datadir': fs.is_absolute(datadir) ? datadir : prefix / datadir, -}, section: 'Directories') -locations = [] -foreach dep: [ffi, glib, gi, spidermonkey, readline, sysprof_capture] - if dep.type_name() == 'pkgconfig' - locations += 'in @0@'.format(dep.get_pkgconfig_variable('prefix')) - else - locations += dep.type_name() - endif -endforeach -summary({ - 'libffi': '@0@ (@1@)'.format(ffi.version(), locations[0]), - 'GLib': '@0@ (@1@)'.format(glib.version(), locations[1]), - 'GObject introspection': '@0@ (@1@)'.format(gi.version(), locations[2]), - 'SpiderMonkey': '@0@ (@1@, @2@ build)'.format(spidermonkey.version(), - locations[3], nondebug_spidermonkey ? 'release' : 'debug'), -}, section: 'Dependencies') -if build_readline - summary('Readline', '(@0@)'.format(locations[4]), section: 'Dependencies') -endif -if build_profiler - summary('Sysprof', - '@0@ (@1@)'.format(sysprof_capture.version(), locations[5]), - section: 'Dependencies') -endif -summary({ - 'Build type': get_option('buildtype'), - 'Installed tests': get_option('installed_tests'), - '-Bsymbolic-functions': get_option('bsymbolic_functions'), - 'Skip DBus tests': get_option('skip_dbus_tests'), - 'Skip GTK tests': get_option('skip_gtk_tests'), - 'Extra debug logs': get_option('verbose_logs'), - 'Precompiled headers': get_option('b_pch'), -}, section: 'Build options') -summary({ - 'Cairo module': build_cairo, - 'Use readline for input': build_readline, - 'Profiler (Linux only)': build_profiler, - 'Dtrace debugging': get_option('dtrace'), - 'Systemtap debugging': get_option('systemtap'), -}, section: 'Optional features') +message('\n'.join([ + 'Optional features', + '==========================', + 'Build Cairo module: @0@'.format(build_cairo), + 'Use readline for input in interactive shell and debugger: @0@'.format( + build_readline), + 'Build profiler (Linux only): @0@'.format(build_profiler), + 'Build with precompiled headers: @0@'.format(get_option('b_pch')), +])) diff -Nru gjs-1.74.0/modules/cairo-context.cpp gjs-1.72.2/modules/cairo-context.cpp --- gjs-1.74.0/modules/cairo-context.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/cairo-context.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -13,14 +13,15 @@ #include // for JS::NewArrayObject #include #include -#include +#include #include // for JSPROP_READONLY #include #include #include #include // for UniqueChars #include -#include // for JS_NewPlainObject +#include +#include // for JS_SetElement #include "gi/arg-inl.h" #include "gi/arg.h" @@ -85,7 +86,9 @@ return false; \ cfunc(cr, &arg1, &arg2); \ if (cairo_status(cr) == CAIRO_STATUS_SUCCESS) { \ - JS::RootedObject array(context, JS::NewArrayObject(context, 2)); \ + JS::RootedObject array( \ + context, \ + JS::NewArrayObject(context, JS::HandleValueArray::empty())); \ if (!array) \ return false; \ JS::RootedValue r(context, JS::NumberValue(arg1)); \ @@ -104,7 +107,9 @@ _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(method) \ cfunc(cr, &arg1, &arg2); \ if (cairo_status(cr) == CAIRO_STATUS_SUCCESS) { \ - JS::RootedObject array(context, JS::NewArrayObject(context, 2)); \ + JS::RootedObject array( \ + context, \ + JS::NewArrayObject(context, JS::HandleValueArray::empty())); \ if (!array) \ return false; \ JS::RootedValue r(context, JS::NumberValue(arg1)); \ @@ -123,7 +128,9 @@ _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(method) \ cfunc(cr, &arg1, &arg2, &arg3, &arg4); \ { \ - JS::RootedObject array(context, JS::NewArrayObject(context, 4)); \ + JS::RootedObject array( \ + context, \ + JS::NewArrayObject(context, JS::HandleValueArray::empty())); \ if (!array) \ return false; \ JS::RootedValue r(context, JS::NumberValue(arg1)); \ @@ -261,7 +268,7 @@ return cr; } -void CairoContext::finalize_impl(JS::GCContext*, cairo_t* cr) { +void CairoContext::finalize_impl(JSFreeOp*, cairo_t* cr) { if (!cr) return; cairo_destroy(cr); @@ -353,11 +360,16 @@ _GJS_CAIRO_CONTEXT_DEFINE_FUNC2FFAFF(userToDevice, cairo_user_to_device, "x", "y") _GJS_CAIRO_CONTEXT_DEFINE_FUNC2FFAFF(userToDeviceDistance, cairo_user_to_device_distance, "x", "y") -bool CairoContext::dispose(JSContext* context, unsigned argc, JS::Value* vp) { +GJS_JSAPI_RETURN_CONVENTION +static bool +dispose_func(JSContext *context, + unsigned argc, + JS::Value *vp) +{ _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj); cairo_destroy(cr); - CairoContext::unset_private(obj); + JS::SetPrivate(obj, nullptr); rec.rval().setUndefined(); return true; @@ -816,7 +828,7 @@ // clang-format off const JSFunctionSpec CairoContext::proto_funcs[] = { - JS_FN("$dispose", &CairoContext::dispose, 0, 0), + JS_FN("$dispose", dispose_func, 0, 0), JS_FN("appendPath", appendPath_func, 0, 0), JS_FN("arc", arc_func, 0, 0), JS_FN("arcNegative", arcNegative_func, 0, 0), diff -Nru gjs-1.74.0/modules/cairo-path.cpp gjs-1.72.2/modules/cairo-path.cpp --- gjs-1.74.0/modules/cairo-path.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/cairo-path.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -6,12 +6,14 @@ #include #include +#include // for g_assert +#include #include // for JSPROP_READONLY #include #include #include -#include // for JS_NewObjectWithGivenProto +#include #include "modules/cairo-private.h" @@ -36,14 +38,15 @@ if (!wrapper) return nullptr; - CairoPath::init_private(wrapper, ptr); + g_assert(!JS::GetPrivate(wrapper)); + JS::SetPrivate(wrapper, ptr); debug_lifecycle(ptr, wrapper, "take_c_ptr"); return wrapper; } -void CairoPath::finalize_impl(JS::GCContext*, cairo_path_t* path) { +void CairoPath::finalize_impl(JSFreeOp*, cairo_path_t* path) { if (!path) return; cairo_path_destroy(path); diff -Nru gjs-1.74.0/modules/cairo-pattern.cpp gjs-1.72.2/modules/cairo-pattern.cpp --- gjs-1.74.0/modules/cairo-pattern.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/cairo-pattern.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -15,7 +15,6 @@ #include #include -#include "gi/cwrapper.h" #include "gjs/jsapi-class.h" #include "gjs/jsapi-util.h" #include "gjs/macros.h" @@ -65,13 +64,14 @@ /** * CairoPattern::finalize_impl: + * @fop: the free op * @pattern: pointer to free * * Destroys the resources associated with a pattern wrapper. * * This is mainly used for subclasses. */ -void CairoPattern::finalize_impl(JS::GCContext*, cairo_pattern_t* pattern) { +void CairoPattern::finalize_impl(JSFreeOp*, cairo_pattern_t* pattern) { if (!pattern) return; cairo_pattern_destroy(pattern); @@ -136,6 +136,5 @@ return nullptr; } - return JS::GetMaybePtrFromReservedSlot( - pattern_wrapper, CairoPattern::POINTER); + return static_cast(JS::GetPrivate(pattern_wrapper)); } diff -Nru gjs-1.74.0/modules/cairo-private.h gjs-1.72.2/modules/cairo-private.h --- gjs-1.74.0/modules/cairo-private.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/cairo-private.h 2022-08-08 05:05:12.000000000 +0000 @@ -55,7 +55,7 @@ static cairo_region_t* constructor_impl(JSContext* cx, const JS::CallArgs& args); - static void finalize_impl(JS::GCContext*, cairo_region_t* cr); + static void finalize_impl(JSFreeOp* fop, cairo_region_t* cr); static const JSFunctionSpec proto_funcs[]; static const JSPropertySpec proto_props[]; @@ -69,7 +69,7 @@ CairoRegion::define_gtype_prop, }; static constexpr JSClass klass = { - "Region", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "Region", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoRegion::class_ops, &CairoRegion::class_spec}; }; @@ -95,7 +95,7 @@ GJS_JSAPI_RETURN_CONVENTION static cairo_t* constructor_impl(JSContext* cx, const JS::CallArgs& args); - static void finalize_impl(JS::GCContext*, cairo_t* cr); + static void finalize_impl(JSFreeOp* fop, cairo_t* cr); static const JSFunctionSpec proto_funcs[]; static const JSPropertySpec proto_props[]; @@ -109,11 +109,8 @@ CairoContext::define_gtype_prop, }; static constexpr JSClass klass = { - "Context", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "Context", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoContext::class_ops, &CairoContext::class_spec}; - - GJS_JSAPI_RETURN_CONVENTION - static bool dispose(JSContext* cx, unsigned argc, JS::Value* vp); }; void gjs_cairo_context_init(void); @@ -133,7 +130,7 @@ GjsGlobalSlot::PROTOTYPE_cairo_path; static constexpr GjsDebugTopic DEBUG_TOPIC = GJS_DEBUG_CAIRO; - static void finalize_impl(JS::GCContext*, cairo_path_t* path); + static void finalize_impl(JSFreeOp* fop, cairo_path_t* path); static const JSPropertySpec proto_props[]; static constexpr js::ClassSpec class_spec = { @@ -146,7 +143,7 @@ nullptr, // finishInit }; static constexpr JSClass klass = { - "Path", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "Path", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoPath::class_ops, &CairoPath::class_spec}; public: @@ -174,7 +171,7 @@ static GType gtype() { return CAIRO_GOBJECT_TYPE_SURFACE; } - static void finalize_impl(JS::GCContext*, cairo_surface_t* surface); + static void finalize_impl(JSFreeOp* fop, cairo_surface_t* surface); static const JSFunctionSpec proto_funcs[]; static const JSPropertySpec proto_props[]; @@ -188,7 +185,7 @@ &CairoSurface::define_gtype_prop, }; static constexpr JSClass klass = { - "Surface", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "Surface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoSurface::class_ops, &CairoSurface::class_spec}; static cairo_surface_t* copy_ptr(cairo_surface_t* surface) { @@ -232,15 +229,14 @@ &CairoSurface::define_gtype_prop, }; static constexpr JSClass klass = { - "ImageSurface", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "ImageSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoSurface::class_ops, &CairoImageSurface::class_spec}; static cairo_surface_t* copy_ptr(cairo_surface_t* surface) { return cairo_surface_reference(surface); } - static void finalize_impl(JS::GCContext*, cairo_surface_t*) {} + static void finalize_impl(JSFreeOp*, cairo_surface_t*) {} GJS_JSAPI_RETURN_CONVENTION static cairo_surface_t* constructor_impl(JSContext* cx, @@ -272,15 +268,14 @@ &CairoSurface::define_gtype_prop, }; static constexpr JSClass klass = { - "PSSurface", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "PSSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoSurface::class_ops, &CairoPSSurface::class_spec}; static cairo_surface_t* copy_ptr(cairo_surface_t* surface) { return cairo_surface_reference(surface); } - static void finalize_impl(JS::GCContext*, cairo_surface_t*) {} + static void finalize_impl(JSFreeOp*, cairo_surface_t*) {} GJS_JSAPI_RETURN_CONVENTION static cairo_surface_t* constructor_impl(JSContext* cx, @@ -318,15 +313,14 @@ &CairoSurface::define_gtype_prop, }; static constexpr JSClass klass = { - "PDFSurface", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "PDFSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoSurface::class_ops, &CairoPDFSurface::class_spec}; static cairo_surface_t* copy_ptr(cairo_surface_t* surface) { return cairo_surface_reference(surface); } - static void finalize_impl(JS::GCContext*, cairo_surface_t*) {} + static void finalize_impl(JSFreeOp*, cairo_surface_t*) {} GJS_JSAPI_RETURN_CONVENTION static cairo_surface_t* constructor_impl(JSContext* cx, @@ -364,15 +358,14 @@ &CairoSurface::define_gtype_prop, }; static constexpr JSClass klass = { - "SVGSurface", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "SVGSurface", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoSurface::class_ops, &CairoSVGSurface::class_spec}; static cairo_surface_t* copy_ptr(cairo_surface_t* surface) { return cairo_surface_reference(surface); } - static void finalize_impl(JS::GCContext*, cairo_surface_t*) {} + static void finalize_impl(JSFreeOp*, cairo_surface_t*) {} GJS_JSAPI_RETURN_CONVENTION static cairo_surface_t* constructor_impl(JSContext* cx, @@ -417,7 +410,7 @@ &CairoPattern::define_gtype_prop, }; static constexpr JSClass klass = { - "Pattern", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "Pattern", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoPattern::class_ops, &CairoPattern::class_spec}; static GType gtype() { return CAIRO_GOBJECT_TYPE_PATTERN; } @@ -430,7 +423,7 @@ static bool getType_func(JSContext* context, unsigned argc, JS::Value* vp); protected: - static void finalize_impl(JS::GCContext*, cairo_pattern_t* pattern); + static void finalize_impl(JSFreeOp* fop, cairo_pattern_t* pattern); public: static cairo_pattern_t* for_js(JSContext* cx, @@ -466,10 +459,10 @@ &CairoPattern::define_gtype_prop, }; static constexpr JSClass klass = { - "Gradient", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "Gradient", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoPattern::class_ops, &CairoGradient::class_spec}; - static void finalize_impl(JS::GCContext*, cairo_pattern_t*) {} + static void finalize_impl(JSFreeOp*, cairo_pattern_t*) {} }; class CairoLinearGradient @@ -497,8 +490,7 @@ &CairoPattern::define_gtype_prop, }; static constexpr JSClass klass = { - "LinearGradient", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "LinearGradient", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoPattern::class_ops, &CairoLinearGradient::class_spec}; static cairo_pattern_t* copy_ptr(cairo_pattern_t* pattern) { @@ -509,7 +501,7 @@ static cairo_pattern_t* constructor_impl(JSContext* cx, const JS::CallArgs& args); - static void finalize_impl(JS::GCContext*, cairo_pattern_t*) {} + static void finalize_impl(JSFreeOp*, cairo_pattern_t*) {} }; class CairoRadialGradient @@ -537,8 +529,7 @@ &CairoPattern::define_gtype_prop, }; static constexpr JSClass klass = { - "RadialGradient", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "RadialGradient", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoPattern::class_ops, &CairoRadialGradient::class_spec}; static cairo_pattern_t* copy_ptr(cairo_pattern_t* pattern) { @@ -549,7 +540,7 @@ static cairo_pattern_t* constructor_impl(JSContext* cx, const JS::CallArgs& args); - static void finalize_impl(JS::GCContext*, cairo_pattern_t*) {} + static void finalize_impl(JSFreeOp*, cairo_pattern_t*) {} }; class CairoSurfacePattern @@ -577,8 +568,7 @@ &CairoPattern::define_gtype_prop, }; static constexpr JSClass klass = { - "SurfacePattern", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "SurfacePattern", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoPattern::class_ops, &CairoSurfacePattern::class_spec}; static cairo_pattern_t* copy_ptr(cairo_pattern_t* pattern) { @@ -589,7 +579,7 @@ static cairo_pattern_t* constructor_impl(JSContext* cx, const JS::CallArgs& args); - static void finalize_impl(JS::GCContext*, cairo_pattern_t*) {} + static void finalize_impl(JSFreeOp*, cairo_pattern_t*) {} }; class CairoSolidPattern : public CWrapper { @@ -615,15 +605,14 @@ &CairoPattern::define_gtype_prop, }; static constexpr JSClass klass = { - "SolidPattern", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_BACKGROUND_FINALIZE, + "SolidPattern", JSCLASS_HAS_PRIVATE | JSCLASS_BACKGROUND_FINALIZE, &CairoPattern::class_ops, &CairoSolidPattern::class_spec}; static cairo_pattern_t* copy_ptr(cairo_pattern_t* pattern) { return cairo_pattern_reference(pattern); } - static void finalize_impl(JS::GCContext*, cairo_pattern_t*) {} + static void finalize_impl(JSFreeOp*, cairo_pattern_t*) {} }; #endif // MODULES_CAIRO_PRIVATE_H_ diff -Nru gjs-1.74.0/modules/cairo-region.cpp gjs-1.72.2/modules/cairo-region.cpp --- gjs-1.74.0/modules/cairo-region.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/cairo-region.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -9,13 +9,12 @@ #include #include -#include #include // for JSPROP_READONLY #include #include #include #include -#include // for JS_NewPlainObject +#include // for JS_GetPropertyById, JS_SetPropert... #include "gi/arg-inl.h" #include "gi/arg.h" @@ -220,7 +219,7 @@ return cairo_region_create(); } -void CairoRegion::finalize_impl(JS::GCContext*, cairo_region_t* region) { +void CairoRegion::finalize_impl(JSFreeOp*, cairo_region_t* region) { if (!region) return; diff -Nru gjs-1.74.0/modules/cairo-surface.cpp gjs-1.72.2/modules/cairo-surface.cpp --- gjs-1.74.0/modules/cairo-surface.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/cairo-surface.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -207,13 +207,14 @@ /** * CairoSurface::finalize_impl: + * @fop: the free op * @surface: the pointer to finalize * * Destroys the resources associated with a surface wrapper. * * This is mainly used for subclasses. */ -void CairoSurface::finalize_impl(JS::GCContext*, cairo_surface_t* surface) { +void CairoSurface::finalize_impl(JSFreeOp*, cairo_surface_t* surface) { if (!surface) return; cairo_surface_destroy(surface); @@ -271,8 +272,7 @@ return nullptr; } - return JS::GetMaybePtrFromReservedSlot( - surface_wrapper, CairoSurface::POINTER); + return static_cast(JS::GetPrivate(surface_wrapper)); } [[nodiscard]] static bool surface_to_g_argument( diff -Nru gjs-1.74.0/modules/console.cpp gjs-1.72.2/modules/console.cpp --- gjs-1.74.0/modules/console.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/console.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -27,28 +27,20 @@ #include #include // for g_fprintf -#include #include -#include // for JS_EncodeStringToUTF8 #include #include #include #include -#include #include #include #include -#include // for UniqueChars -#include -#include #include -#include // for JS_NewPlainObject +#include // for JS_IsExceptionPending, Exce... #include "gjs/atoms.h" #include "gjs/context-private.h" -#include "gjs/global.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "modules/console.h" namespace mozilla { @@ -154,26 +146,11 @@ return true; } -std::string print_string_value(JSContext* cx, JS::HandleValue v_string) { - if (!v_string.isString()) - return "[unexpected result from printing value]"; - - JS::RootedString printed_string(cx, v_string.toString()); - JS::AutoSaveExceptionState exc_state(cx); - JS::UniqueChars chars(JS_EncodeStringToUTF8(cx, printed_string)); - exc_state.restore(); - if (!chars) - return "[error printing value]"; - - return chars.get(); -} - /* Return value of false indicates an uncatchable exception, rather than any * exception. (This is because the exception should be auto-printed around the * invocation of this function.) */ [[nodiscard]] static bool gjs_console_eval_and_print(JSContext* cx, - JS::HandleObject global, const std::string& bytes, int lineno) { JS::SourceText source; @@ -196,23 +173,7 @@ if (result.isUndefined()) return true; - JS::AutoSaveExceptionState exc_state(cx); - JS::RootedValue v_printed_string(cx); - JS::RootedValue v_pretty_print( - cx, gjs_get_global_slot(global, GjsGlobalSlot::PRETTY_PRINT_FUNC)); - bool ok = JS::Call(cx, global, v_pretty_print, JS::HandleValueArray(result), - &v_printed_string); - if (!ok) - gjs_log_exception(cx); - exc_state.restore(); - - if (ok) { - g_fprintf(stdout, "%s\n", - print_string_value(cx, v_printed_string).c_str()); - } else { - g_fprintf(stdout, "[error printing value]\n"); - } - + g_fprintf(stdout, "%s\n", gjs_value_debug_string(cx, result).c_str()); return true; } @@ -290,7 +251,7 @@ bool ok; { AutoReportException are(context); - ok = gjs_console_eval_and_print(context, global, buffer, startline); + ok = gjs_console_eval_and_print(context, buffer, startline); } exit_warning = false; diff -Nru gjs-1.74.0/modules/core/overrides/Gio.js gjs-1.72.2/modules/core/overrides/Gio.js --- gjs-1.74.0/modules/core/overrides/Gio.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/core/overrides/Gio.js 2022-08-08 05:05:12.000000000 +0000 @@ -185,22 +185,8 @@ let i, methods = info.methods; for (i = 0; i < methods.length; i++) { var method = methods[i]; - let remoteMethod = _makeProxyMethod(methods[i], false); - this[`${method.name}Remote`] = remoteMethod; + this[`${method.name}Remote`] = _makeProxyMethod(methods[i], false); this[`${method.name}Sync`] = _makeProxyMethod(methods[i], true); - this[`${method.name}Async`] = function (...args) { - return new Promise((resolve, reject) => { - args.push((result, error, fdList) => { - if (error) - reject(error); - else if (fdList) - resolve([result, fdList]); - else - resolve(result); - }); - remoteMethod.call(this, ...args); - }); - }; } let properties = info.properties; @@ -417,30 +403,23 @@ yield this.get_item(_index++); } -function _promisify(proto, asyncFunc, finishFunc = undefined) { +function _promisify(proto, asyncFunc, + finishFunc = `${asyncFunc.replace(/_(begin|async)$/, '')}_finish`) { if (proto[asyncFunc] === undefined) throw new Error(`${proto} has no method named ${asyncFunc}`); - if (finishFunc === undefined) { - if (asyncFunc.endsWith('_begin') || asyncFunc.endsWith('_async')) - finishFunc = `${asyncFunc.slice(0, -5)}finish`; - else - finishFunc = `${asyncFunc}_finish`; - } - if (proto[finishFunc] === undefined) throw new Error(`${proto} has no method named ${finishFunc}`); - const originalFuncName = `_original_${asyncFunc}`; - if (proto[originalFuncName] !== undefined) + if (proto[`_original_${asyncFunc}`] !== undefined) return; - proto[originalFuncName] = proto[asyncFunc]; + proto[`_original_${asyncFunc}`] = proto[asyncFunc]; proto[asyncFunc] = function (...args) { - if (args.length === this[originalFuncName].length) - return this[originalFuncName](...args); + if (!args.every(arg => typeof arg !== 'function')) + return this[`_original_${asyncFunc}`](...args); return new Promise((resolve, reject) => { - let {stack: callStack} = new Error(); - this[originalFuncName](...args, function (source, res) { + const callStack = new Error().stack.split('\n').filter(line => !line.match(/promisify/)).join('\n'); + this[`_original_${asyncFunc}`](...args, function (source, res) { try { const result = source !== null && source[finishFunc] !== undefined ? source[finishFunc](res) @@ -449,8 +428,6 @@ result.shift(); resolve(result); } catch (error) { - callStack = callStack.split('\n').filter(line => - line.indexOf('_promisify/') === -1).join('\n'); if (error.stack) error.stack += `### Promise created here: ###\n${callStack}`; else @@ -462,18 +439,17 @@ }; } -function _notIntrospectableError(funcName, replacement) { - return new Error(`${funcName} is not introspectable. Use ${replacement} instead.`); -} - -function _warnNotIntrospectable(funcName, replacement) { - logError(_notIntrospectableError(funcName, replacement)); -} - function _init() { Gio = this; Gio.DBus = { + get session() { + return Gio.bus_get_sync(Gio.BusType.SESSION, null); + }, + get system() { + return Gio.bus_get_sync(Gio.BusType.SYSTEM, null); + }, + // Namespace some functions get: Gio.bus_get, get_finish: Gio.bus_get_finish, @@ -488,21 +464,6 @@ unwatch_name: Gio.bus_unwatch_name, }; - Object.defineProperties(Gio.DBus, { - 'session': { - get() { - return Gio.bus_get_sync(Gio.BusType.SESSION, null); - }, - enumerable: false, - }, - 'system': { - get() { - return Gio.bus_get_sync(Gio.BusType.SYSTEM, null); - }, - enumerable: false, - }, - }); - Gio.DBusConnection.prototype.watch_name = function (name, flags, appeared, vanished) { return Gio.bus_watch_name_on_connection(this, name, flags, appeared, vanished); }; @@ -553,119 +514,6 @@ return this.replace_contents_bytes_async(contents, etag, make_backup, flags, cancellable, callback); }; - // Best-effort attempt to replace set_attribute(), which is not - // introspectable due to the pointer argument - Gio.File.prototype.set_attribute = function set_attribute(attribute, type, value, flags, cancellable) { - _warnNotIntrospectable('Gio.File.prototype.set_attribute', 'set_attribute_{type}'); - - switch (type) { - case Gio.FileAttributeType.STRING: - return this.set_attribute_string(attribute, value, flags, cancellable); - case Gio.FileAttributeType.BYTE_STRING: - return this.set_attribute_byte_string(attribute, value, flags, cancellable); - case Gio.FileAttributeType.UINT32: - return this.set_attribute_uint32(attribute, value, flags, cancellable); - case Gio.FileAttributeType.INT32: - return this.set_attribute_int32(attribute, value, flags, cancellable); - case Gio.FileAttributeType.UINT64: - return this.set_attribute_uint64(attribute, value, flags, cancellable); - case Gio.FileAttributeType.INT64: - return this.set_attribute_int64(attribute, value, flags, cancellable); - case Gio.FileAttributeType.INVALID: - case Gio.FileAttributeType.BOOLEAN: - case Gio.FileAttributeType.OBJECT: - case Gio.FileAttributeType.STRINGV: - throw _notIntrospectableError('This attribute type', 'Gio.FileInfo'); - } - }; - - Gio.FileInfo.prototype.set_attribute = function set_attribute(attribute, type, value) { - _warnNotIntrospectable('Gio.FileInfo.prototype.set_attribute', 'set_attribute_{type}'); - - switch (type) { - case Gio.FileAttributeType.INVALID: - return this.remove_attribute(attribute); - case Gio.FileAttributeType.STRING: - return this.set_attribute_string(attribute, value); - case Gio.FileAttributeType.BYTE_STRING: - return this.set_attribute_byte_string(attribute, value); - case Gio.FileAttributeType.BOOLEAN: - return this.set_attribute_boolean(attribute, value); - case Gio.FileAttributeType.UINT32: - return this.set_attribute_uint32(attribute, value); - case Gio.FileAttributeType.INT32: - return this.set_attribute_int32(attribute, value); - case Gio.FileAttributeType.UINT64: - return this.set_attribute_uint64(attribute, value); - case Gio.FileAttributeType.INT64: - return this.set_attribute_int64(attribute, value); - case Gio.FileAttributeType.OBJECT: - return this.set_attribute_object(attribute, value); - case Gio.FileAttributeType.STRINGV: - return this.set_attribute_stringv(attribute, value); - } - }; - - Gio.FileEnumerator.prototype[Symbol.iterator] = function* FileEnumeratorIterator() { - while (true) { - try { - const info = this.next_file(null); - if (info === null) - break; - yield info; - } catch (err) { - this.close(null); - throw err; - } - } - this.close(null); - }; - - Gio.FileEnumerator.prototype[Symbol.asyncIterator] = async function* AsyncFileEnumatorIterator() { - const self = this; - - function next() { - return new Promise((resolve, reject) => { - self.next_files_async(1, Gio.PRIORITY_DEFAULT, null, (_self, res) => { - try { - const files = self.next_files_finish(res); - resolve(files.length === 0 ? null : files[0]); - } catch (err) { - reject(err); - } - }); - }); - } - - function close() { - return new Promise((resolve, reject) => { - self.close_async(Gio.PRIORITY_DEFAULT, null, (_self, res) => { - try { - resolve(self.close_finish(res)); - } catch (err) { - reject(err); - } - }); - }); - } - - while (true) { - try { - // eslint-disable-next-line no-await-in-loop - const info = await next(); - if (info === null) - break; - yield info; - } catch (err) { - // eslint-disable-next-line no-await-in-loop - await close(); - throw err; - } - } - - return close(); - }; - // Override Gio.Settings and Gio.SettingsSchema - the C API asserts if // trying to access a nonexistent schema or key, which is not handy for // shell-extension writers @@ -773,28 +621,4 @@ get_child: createCheckedMethod('get_child', '_checkChild'), }); - - // ActionMap - // add_action_entries is not introspectable - // https://gitlab.gnome.org/GNOME/gjs/-/issues/407 - Gio.ActionMap.prototype.add_action_entries = function add_action_entries(entries) { - for (const {name, activate, parameter_type, state, change_state} of entries) { - if (typeof parameter_type === 'string' && !GLib.variant_type_string_is_valid(parameter_type)) - throw new Error(`parameter_type "${parameter_type}" is not a valid VariantType`); - - const action = new Gio.SimpleAction({ - name, - parameter_type: typeof parameter_type === 'string' ? new GLib.VariantType(parameter_type) : null, - state: typeof state === 'string' ? GLib.Variant.parse(null, state, null, null) : null, - }); - - if (typeof activate === 'function') - action.connect('activate', activate.bind(action)); - - if (typeof change_state === 'function') - action.connect('change-state', change_state.bind(action)); - - this.add_action(action); - } - }; } diff -Nru gjs-1.74.0/modules/core/overrides/GLib.js gjs-1.72.2/modules/core/overrides/GLib.js --- gjs-1.74.0/modules/core/overrides/GLib.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/core/overrides/GLib.js 2022-08-08 05:05:12.000000000 +0000 @@ -505,27 +505,4 @@ const invalidRegex = new RegExp(`[^${escapedValidArray.join('')}]`, 'g'); return string.replace(invalidRegex, substitutor); }; - - // Prevent user code from calling GThread functions which always crash - this.Thread.new = function () { - throw _notIntrospectableError('GLib.Thread.new()', - 'GIO asynchronous methods or Promise()'); - }; - - this.Thread.try_new = function () { - throw _notIntrospectableError('GLib.Thread.try_new()', - 'GIO asynchronous methods or Promise()'); - }; - - this.Thread.exit = function () { - throw new Error('\'GLib.Thread.exit()\' may not be called in GJS'); - }; - - this.Thread.prototype.ref = function () { - throw new Error('\'GLib.Thread.ref()\' may not be called in GJS'); - }; - - this.Thread.prototype.unref = function () { - throw new Error('\'GLib.Thread.unref()\' may not be called in GJS'); - }; } diff -Nru gjs-1.74.0/modules/core/overrides/GObject.js gjs-1.72.2/modules/core/overrides/GObject.js --- gjs-1.74.0/modules/core/overrides/GObject.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/core/overrides/GObject.js 2022-08-08 05:05:12.000000000 +0000 @@ -689,10 +689,6 @@ return GjsPrivate.g_object_bind_property_full(this, ...args); }; - GObject.BindingGroup.prototype.bind_full = function (...args) { - return GjsPrivate.g_binding_group_bind_full(this, ...args); - }; - // fake enum for signal accumulators, keep in sync with gi/object.c GObject.AccumulatorType = { NONE: 0, diff -Nru gjs-1.74.0/modules/print.cpp gjs-1.72.2/modules/print.cpp --- gjs-1.74.0/modules/print.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/print.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -13,17 +13,13 @@ #include // for JS_EncodeStringToUTF8 #include #include -#include // for JS_DefineFunctions #include // for JS_FN, JSFunctionSpec, JS_FS_END #include #include #include // for UniqueChars -#include -#include // for JS_NewPlainObject +#include -#include "gjs/global.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "modules/print.h" GJS_JSAPI_RETURN_CONVENTION @@ -139,57 +135,12 @@ return true; } -// The pretty-print functionality is best written in JS, but needs to be used -// from C++ code. This stores the prettyPrint() function in a slot on the global -// object so that it can be used internally by the Console module. -// This function is not available to user code. -GJS_JSAPI_RETURN_CONVENTION -static bool set_pretty_print_function(JSContext*, unsigned argc, - JS::Value* vp) { - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - // can only be called internally, so OK to assert correct arguments - g_assert(args.length() == 2 && "setPrettyPrintFunction takes 2 arguments"); - - JS::Value v_global = args[0]; - JS::Value v_func = args[1]; - - g_assert(v_global.isObject() && "first argument must be an object"); - g_assert(v_func.isObject() && "second argument must be an object"); - - gjs_set_global_slot(&v_global.toObject(), GjsGlobalSlot::PRETTY_PRINT_FUNC, - v_func); - - args.rval().setUndefined(); - return true; -} - -GJS_JSAPI_RETURN_CONVENTION -static bool get_pretty_print_function(JSContext*, unsigned argc, - JS::Value* vp) { - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - g_assert(args.length() == 1 && "getPrettyPrintFunction takes 1 arguments"); - - JS::Value v_global = args[0]; - - g_assert(v_global.isObject() && "argument must be an object"); - - JS::Value pretty_print = gjs_get_global_slot( - &v_global.toObject(), GjsGlobalSlot::PRETTY_PRINT_FUNC); - - args.rval().set(pretty_print); - return true; -} - // clang-format off static constexpr JSFunctionSpec funcs[] = { JS_FN("log", gjs_log, 1, GJS_MODULE_PROP_FLAGS), JS_FN("logError", gjs_log_error, 2, GJS_MODULE_PROP_FLAGS), JS_FN("print", gjs_print, 0, GJS_MODULE_PROP_FLAGS), JS_FN("printerr", gjs_printerr, 0, GJS_MODULE_PROP_FLAGS), - JS_FN("setPrettyPrintFunction", set_pretty_print_function, 1, GJS_MODULE_PROP_FLAGS), - JS_FN("getPrettyPrintFunction", get_pretty_print_function, 1, GJS_MODULE_PROP_FLAGS), JS_FS_END}; // clang-format on diff -Nru gjs-1.74.0/modules/script/_bootstrap/debugger.js gjs-1.72.2/modules/script/_bootstrap/debugger.js --- gjs-1.74.0/modules/script/_bootstrap/debugger.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/script/_bootstrap/debugger.js 2022-08-08 05:05:12.000000000 +0000 @@ -36,6 +36,17 @@ return typeof v !== 'object' || v === null ? uneval(v) : `[object ${v.class}]`; } +function summarizeObject(dv) { + const obj = {}; + for (var name of dv.getOwnPropertyNames()) { + var v = dv.getOwnPropertyDescriptor(name).value; + if (v instanceof Debugger.Object) + v = '(...)'; + obj[name] = v; + } + return obj; +} + function debuggeeValueToString(dv, style = {pretty: options.pretty}) { // Special sentinel values returned by Debugger.Environment.getVariable() if (typeof dv === 'object' && dv !== null) { @@ -60,11 +71,10 @@ } if (style.brief) - return [dvrepr, dvrepr]; + return [dvrepr, JSON.stringify(summarizeObject(dv), null, 4)]; const str = debuggeeGlobalWrapper.executeInGlobalWithBindings( - 'imports._print.getPrettyPrintFunction(globalThis)(v)', {v: dv}); - + 'JSON.stringify(v, null, 4)', {v: dv}); if ('throw' in str) { if (style.noerror) return [dvrepr, undefined]; @@ -314,12 +324,10 @@ function doPrint(expr, style) { // This is the real deal. - expr = `(${expr})`; const cv = saveExcursion( () => focusedFrame === null ? debuggeeGlobalWrapper.executeInGlobalWithBindings(expr, debuggeeValues) : focusedFrame.evalWithBindings(expr, debuggeeValues)); - if (cv === null) { print('Debuggee died.'); } else if ('return' in cv) { diff -Nru gjs-1.74.0/modules/script/_bootstrap/default.js gjs-1.72.2/modules/script/_bootstrap/default.js --- gjs-1.74.0/modules/script/_bootstrap/default.js 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/script/_bootstrap/default.js 2022-08-08 05:05:12.000000000 +0000 @@ -5,96 +5,7 @@ (function (exports) { 'use strict'; - const { - print, - printerr, - log: nativeLog, - logError: nativeLogError, - setPrettyPrintFunction, - } = imports._print; - - function log(...args) { - return nativeLog(args.map(arg => typeof arg === 'string' ? arg : prettyPrint(arg)).join(' ')); - } - - function logError(e, ...args) { - if (args.length === 0) - return nativeLogError(e); - return nativeLogError(e, args.map(arg => typeof arg === 'string' ? arg : prettyPrint(arg)).join(' ')); - } - - function prettyPrint(value) { - if (value.toString === Object.prototype.toString || value.toString === Array.prototype.toString || value.toString === Function.prototype.toString || value.toString === Date.prototype.toString) { - const printedObjects = new WeakSet(); - switch (typeof value) { - case 'object': - return formatObject(value, printedObjects); - case 'function': - return formatFunction(value); - default: - return value.toString(); - } - } else { - if (typeof value === 'string') - return JSON.stringify(value); - return value.toString(); - } - } - - function formatObject(obj, printedObjects) { - printedObjects.add(obj); - if (Array.isArray(obj)) - return formatArray(obj, printedObjects).toString(); - - if (obj instanceof Date) - return formatDate(obj); - - if (obj[Symbol.toStringTag] === 'GIRepositoryNamespace') - return obj.toString(); - - const formattedObject = []; - for (const [key, value] of Object.entries(obj)) { - switch (typeof value) { - case 'object': - if (printedObjects.has(value)) - formattedObject.push(`${key}: [Circular]`); - else - formattedObject.push(`${key}: ${formatObject(value, printedObjects)}`); - break; - case 'function': - formattedObject.push(`${key}: ${formatFunction(value)}`); - break; - case 'string': - formattedObject.push(`${key}: "${value}"`); - break; - default: - formattedObject.push(`${key}: ${value}`); - break; - } - } - return Object.keys(formattedObject).length === 0 ? '{}' - : `{ ${formattedObject.join(', ')} }`; - } - - function formatArray(arr, printedObjects) { - const formattedArray = []; - for (const [key, value] of arr.entries()) { - if (printedObjects.has(value)) - formattedArray[key] = '[Circular]'; - else - formattedArray[key] = prettyPrint(value); - } - return `[${formattedArray.join(', ')}]`; - } - - function formatDate(date) { - return date.toISOString(); - } - - function formatFunction(func) { - let funcOutput = `[ Function: ${func.name} ]`; - return funcOutput; - } + const {print, printerr, log, logError} = imports._print; Object.defineProperties(exports, { ARGV: { @@ -130,5 +41,4 @@ value: logError, }, }); - setPrettyPrintFunction(exports, prettyPrint); })(globalThis); diff -Nru gjs-1.74.0/modules/system.cpp gjs-1.72.2/modules/system.cpp --- gjs-1.74.0/modules/system.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/modules/system.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -18,14 +18,13 @@ #include // for ResetTimeZone #include // for JS_GC #include -#include #include // for JSPROP_READONLY #include #include #include #include // for NullValue #include -#include // for JS_GetFunctionObject, JS_NewPlainObject +#include // for JS_DefinePropertyById, JS_DefineF... #include // for GetFunctionNativeReserved, NewFunctionByIdW... #include "gi/object.h" @@ -33,7 +32,6 @@ #include "gjs/context-private.h" #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util.h" -#include "gjs/macros.h" #include "gjs/profiler-private.h" #include "modules/system.h" #include "util/log.h" diff -Nru gjs-1.74.0/NEWS gjs-1.72.2/NEWS --- gjs-1.74.0/NEWS 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/NEWS 2022-08-08 05:05:12.000000000 +0000 @@ -1,81 +1,3 @@ -Version 1.74.0 --------------- - -- Many improvements to the examples and documentation. - -- Build fixes for Windows. - -- Overrides to certain non-introspectable functions that will now gracefully - throw an exception instead of crashing. - -- Closed bugs and merge requests: - * Various maintenance [!786, Philip Chimento] - * http example not reliable, relies on server provided content-length. [#498, - !787, Andy Holmes] - * Gio set_attribute SIGSEGV (Address boundary error) [#496, !788, Philip - Chimento] - * Fix Visual Studio builds after migration to SpiderMonkey 102.x [!789, - Chun-wei Fan] - * Update Visual Studio build instructions [!791, Chun-wei Fan] - * doc: reformat for better scraping with DevDocs [!792, Andy Holmes] - * doc: Update Home [!793, Sonny Piers] - * GLib: override GThread functions [!795, Andy Holmes] - -Version 1.73.90 ---------------- - -- Skipped. - -Version 1.72.3 --------------- - -- Fix for crash after build against libffi 3.4.2 ported from the development - branch. - -Version 1.73.2 --------------- - -- New JavaScript features! This version of GJS is based on SpiderMonkey 102, an - upgrade from the previous ESR (Extended Support Release) of SpiderMonkey 91. - Here are the highlights of the new JavaScript features. - For more information, look them up on MDN or devdocs.io. - - * New APIs - + The `Object.hasOwn()` static method can be used as an easier replacement - for `Object.prototype.hasOwnProperty.call(...)`. - + `Intl.supportedValuesOf()` lets you enumerate which calendars, currencies, - collation strategies, numbering systems, time zones, and units are - available for internationalization. - -- It's now possible to use `GObject.BindingGroup.prototype.bind_full()` with JS - functions. Previously this method was unusable in JS. - -- Gio.FileEnumerator is now iterable, both synchronously (with for-of or array - spread syntax) and asynchronously (with for-await-of). - -- Performance improvements in the built-in `imports.signals` module. - -- Many improvements to the examples and documentation. - -- Closed bugs and merge requests: - * Spidermonkey 102 [#487, !765, !785, Evan Welsh, Philip Chimento] - * Object connections / signal emissions optimizations [#485, !758, Marco - Trevisan] - * tests/Gio: Cleanup Gio._promisify [!767, Marco Trevisan] - * Include JUnit reports in builds [!768, Marco Trevisan] - * Integrate pretty print to the debugger [!769, Nasah Kuma] - * doc: Edit GJS description [!771, Sonny Piers] - * doc: note the version `constructor()` became supported [!774, Andy Holmes] - * build: disable sysprof agent for subproject fallback [!775, Christian - Hergert] - * Update CI images [!776, !777, !778, Philip Chimento] - * GListModel.get_n_items returns garbage value [#493, !779, Florian Müllner] - * Add override for g_binding_group_bind_full() [!780, Florian Müllner] - * doc: Modernize examples [!781, Sonny Piers] - * doc: Document byteArray deprecation and migration [!782, Sonny Piers] - * doc: add simple Gtk.TickCallback example [!783, Andy Holmes] - * Make GFileEnumerator iterable and async iterable [!784, Sonny Piers] - Version 1.72.2 -------------- @@ -85,58 +7,6 @@ * gi/arg-cache.cpp: Fix building on Visual Studio [!772, Chun-wei Fan] * doc: Reflect support for constructor with GObject [!773, Sonny Piers] -Version 1.73.1 --------------- - -- The interactive interpreter now displays its output more intelligently, - pretty-printing the properties and values of objects based on their type. This - improvement also applies to the log() and logError() functions. - -- New API: DBus proxy classes now include methods named with the suffix 'Async', - which perform async calls to DBus APIs and return Promises. This is in - addition to the existing suffixes 'Sync' (for blocking calls) and 'Remote' - (for async calls with callbacks.) - -- There is an override for Gio.ActionMap.prototype.add_action_entries(). - Previously this method wouldn't work because it required an array of - Gio.ActionEntry objects, which are not possible to construct in GJS. Now it - can be used with an array of plain objects. (e.g. `this.add_action_entries([ - {name: 'open', activate() { ... }}]);` - -- GJS is now compatible with libffi 3.4.2 and later. All earlier versions of GJS - are not compatible with libffi 3.4.2 and later unless libffi is built with the - --disable-exec-static-tramp flag. - -- GJS now requires Meson 0.54 to build. - -- Closed bugs and merge requests: - * Verbose Object Print Output [#107, !587, Nasah Kuma] - * Add support for JS async calls in DBusProxyWrapper [!731, Sergio Costas] - * Crash after build against libffi 3.4.2 [#428, !737, Evan Welsh] - * Handle reference cycles in new console pretty print function [#469, !739, - Nasah Kuma] - * Gnome-Shell 42 - crash after login (general protection fault) [#479, !740, - Xi Ruoyao] - * Various maintenance [!741, Philip Chimento] - * jsapi-util-strings: Ignore locale to compute the upper case of a char (i.e. - fix implicit properties on Turkish locale) [!742, Marco Trevisan] - * Dockerfile: Install Turkish locale in CI for UTF-8 locale too [!743, Marco - Trevisan] - * Improve pretty-print output for GObject-introspected objects [#476, !744, - Nasah Kuma] - * Expose pretty print function to tests [!745, Nasah Kuma] - * build: track changes to Sysprof meson options [!747, Christian Hergert] - * Make Gio.ActionMap.add_action_entries work [#407, !749, Sonny Piers] - * Make DBus session and system props non-enumerable [!750, Sonny Piers] - * gi/arg-inl: Mark the arg functions as constexpr [!752, Marco Trevisan] - * build: Do not use verbose GJS debug logging in tests by default [!753, Marco - Trevisan] - * minijasmine: Print test JS errors output if any [!754, Marco Trevisan] - * doc: document the existence of the console object in GJS [!759, Andy Holmes] - * arg-cache: Use a switch to select the not-introspectable error [!762, Marco - Trevisan] - * log_set_writer_func is not safe to use [#481, !766, Evan Welsh] - Version 1.72.1 -------------- @@ -158,26 +28,6 @@ - No changes from release candidate 1.71.90. -Version 1.70.2 --------------- - -- Build and compatibility fixes backported from the development branch. - -- Closed bugs and merge requests: - * package: Reverse order of running-from-source checks [!734, Philip Chimento] - -- Fix build error on Darwin [Evan Miller] - -Version 1.68.6 --------------- - -- Build and compatibility fixes backported from the development branch. - -- Closed bugs and merge requests: - * package: Reverse order of running-from-source checks [!734, Philip Chimento] - -- Fix build error on Darwin [Evan Miller] - Version 1.71.90 --------------- diff -Nru gjs-1.74.0/README.md gjs-1.72.2/README.md --- gjs-1.74.0/README.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/README.md 2022-08-08 05:05:12.000000000 +0000 @@ -6,17 +6,13 @@ [![License](https://img.shields.io/badge/License-LGPL%20v2%2B-blue.svg)](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/COPYING) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/COPYING) -GNOME JavaScript +JavaScript bindings for GNOME ============================= -GJS is a JavaScript runtime built on -[Firefox's SpiderMonkey JavaScript engine](https://spidermonkey.dev/) and -the [GNOME platform libraries](https://developer.gnome.org/). - Use the GNOME platform libraries in your JavaScript programs. -GJS powers GNOME Shell, Maps, Characters, Sound Recorder and many other apps. - -If you would like to learn more or get started with GJS, head over to the [documentation](./doc/Home.md). +GJS powers GNOME Shell, Polari, GNOME Documents, and many other apps. +Under the hood it uses SpiderMonkey, Mozilla's JavaScript engine +originally developed for Firefox. ## Installation diff -Nru gjs-1.74.0/README.MSVC.md gjs-1.72.2/README.MSVC.md --- gjs-1.74.0/README.MSVC.md 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/README.MSVC.md 2022-08-08 05:05:12.000000000 +0000 @@ -1,19 +1,19 @@ Instructions for building GJS on Visual Studio or clang-cl ========================================================== Building the GJS on Windows is now supported using Visual Studio -versions 2019 16.5.x or later with or without clang-cl in both 32-bit -and 64-bit (x64) flavors, via Meson. It should be noted that a +versions 2019 or later with or without clang-cl in both 32-bit and +64-bit (x64) flavors, via Meson. It should be noted that a recent-enough Windows SDK from Microsoft is still required if using clang-cl, as we will still use items from the Windows SDK. Recent official binary installers of CLang (which contains clang-cl) -from the LLVM website are known to work to build SpiderMonkey 102 and +from the LLVM website are known to work to build SpiderMonkey 91 and GJS. You will need the following items to build GJS using Visual Studio or clang-cl (they can be built with Visual Studio 2015 or later, unless otherwise noted): --SpiderMonkey 102.x (mozjs-102). This must be built with clang-cl as +-SpiderMonkey 91.x (mozjs-91). This must be built with clang-cl as the Visual Studio compiler is no longer supported for building this. Please see the below section carefully on this... -GObject-Introspection (G-I) 1.61.2 or later @@ -44,8 +44,8 @@ the GJS version that is being built, as GJS depends on ESR (Extended Service Release, a.k.a Long-term support) releases of SpiderMonkey. -You may also be able to obtain the SpiderMonkey 102.x sources via the -FireFox (ESR) or Thunderbird 102.x sources, in $(srcroot)/js. +You may also be able to obtain the SpiderMonkey 91.x sources via the +FireFox (ESR) or Thunderbird 91.x sources, in $(srcroot)/js. Please do note that the build must be done carefully, in addition to the official instructions that are posted on the Mozilla website: @@ -53,40 +53,39 @@ https://firefox-source-docs.mozilla.org/js/build.html You will need to create a .mozconfig file that will describe your build -options for the build in the root directory of the Firefox/ThunderBird 102.x +options for the build in the root directory of the Firefox/ThunderBird 91.x sources. A sample content of the .mozconfig file can be added as follows: ``` ac_add_options --enable-application=js mk_add_options MOZ_MAKE_FLAGS=-j12 +mk_add_options JS_STANDALONE=1 ac_add_options --target=x86_64-pc-mingw32 ac_add_options --host=x86_64-pc-mingw32 ac_add_options --disable-tests ac_add_options --enable-optimize ac_add_options --disable-debug ac_add_options --disable-jemalloc -ac_add_options --prefix=c:/software.b/mozjs102.bin +ac_add_options --prefix=c:/software.b/mozjs91.bin ``` An explanation of the lines above: * `ac_add_options --enable-application=js`: This line is absolutely required, to build SpiderMonkey standalone * `mk_add_options MOZ_MAKE_FLAGS=-j12`: MOZ_MAKE_FLAGS=-jX means X number of parallel processes for the build +* `mk_add_options JS_STANDALONE=1`: Enforce building SpiderMonkey standalone (could be optional) * `ac_add_options --target=x86_64-pc-mingw32`: Target architecture, replace `x86_64` with `aarch64` for ARM64 builds, and with `i686` for 32-bit x86 builds. * `ac_add_options --host=x86_64-pc-mingw32`: Use this as-is, unless building on a 32-bit compiler (replace `x86_64` with `i686`; not recommended) * `ac_add_options --disable-tests`: Save some build time * `ac_add_options --enable-optimize`: Use for release builds of SpiderMonkey. Use `--disable-optimize` instead if building with `--enable-debug` * `ac_add_options --enable-debug`: Include debugging functions, for debug builds. Use `--disable-debug` instead if building with `--enable-optimize` * `ac_add_options --disable-jemalloc`: This is absolutely needed, otherwise GJS will not build and run correctly -* `ac_add_options --prefix=c:/software.b/mozjs102.bin`: Some installation path, change as needed +* `ac_add_options --prefix=c:/software.b/mozjs91.bin`: Some installation path, change as needed If your GJS build crashes upon launch, use Dependency Walker to ensure that -mozjs-102.dll does not depend on mozglue.dll! If it does, or if GJS fails to +mozjs-91.dll does not depend on mozglue.dll! If it does, or if GJS fails to link with missing arena_malloc() and friends symbols, you have built SpiderMoney incorrectly and will need to rebuild SpiderMonkey (with the build options as -noted above) and retry the build. Because SpiderMonkey needs to be built -without jemalloc, enclose the entire `DllMain()` implementation in -`$(srcroot)/js/src/jsapi.cpp` with `#if 0` ... `#endif`, otherwise -SpiderMonkey will fail to link. +noted above) and retry the build. Please also check that `--enable-optimize` is *not* used with `--enable-debug`. You should explicitly enable one and disable the other, as `--enable-debug` @@ -120,28 +119,17 @@ you will need to search for them in $(buildroot), where the PDB file names match the filenames for the DLLs/EXEs in $(buildroot)/dist/bin, and you will need to look for the following .lib files: --mozjs-102.lib +-mozjs-91.lib -js_static.lib (optional) -Due to some bugs that are not yet resolved in upstream SpiderMonkey 102.x, -you may need to do the following after running `./mach build install` and -before attempting to build GJS itself: - -* Copy `$(builddir)/dist/include/js/ProfilingCategoryList.h` to - `$(PREFIX)\include\mozjs-102\js`. - -* Change `$(PREFIX)\include\mozjs-102\mozilla\EnumSet.h` and change line - 329 from `static constexpr size_t kMaxBits = EnumSet().MaxBits();` - to `size_t kMaxBits = EnumSet().MaxBits();`. - You may want to put the .lib's and DLLs/EXEs into $(PREFIX)\lib and $(PREFIX)\bin respectively, and put the headers into -$(PREFIX)\include\mozjs-102 for convenience. +$(PREFIX)\include\mozjs-91 for convenience. -You will need to place the generated mozjs-102.pc pkg-config file into +You will need to place the generated mozjs-91.pc pkg-config file into $(PREFIX)\lib\pkgconfig and ensure that pkg-config can find it by setting PKG_CONFIG_PATH. Ensure that the 'includedir' and 'libdir' -in there is correct so that the mozjs-102.pc can be used correctly in +in there is correct so that the mozjs-91.pc can be used correctly in Visual Studio/clang-cl builds, and replace the `-isystem` with `-I` if building GJS with Visual Studio. You will also need to ensure that the existing GObject-Introspection installation (if used) is on the same @@ -170,9 +158,7 @@ see the Meson documentation for the values accepted by buildtype) You may want to view the build options after the configuration succeeds -by using 'meson configure'. You may need to set the envvar: -`SETUPTOOLS_USE_DISTUTILS=stdlib` for the introspection step to proceed -successfully. A fix for this is being investigated. +by using 'meson configure' When the configuration succeeds, run: ninja diff -Nru gjs-1.74.0/test/extra/Dockerfile gjs-1.72.2/test/extra/Dockerfile --- gjs-1.74.0/test/extra/Dockerfile 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/test/extra/Dockerfile 2022-08-08 05:05:12.000000000 +0000 @@ -3,25 +3,15 @@ # === Build Spidermonkey stage === -FROM registry.fedoraproject.org/fedora:36 AS mozjs-build +FROM registry.fedoraproject.org/fedora:34 AS mozjs-build ARG MOZJS_BRANCH=mozjs91 ARG MOZJS_BUILDDEPS=${MOZJS_BRANCH} ARG BUILD_OPTS= ENV SHELL=/bin/bash -# mozjs91 cannot be built with python3.10 -RUN dnf -y install 'dnf-command(builddep)' \ - autoconf213 \ - clang \ - git \ - llvm \ - llvm-devel \ - make \ - python3.9 \ - rust \ - which \ - xz +RUN dnf -y install 'dnf-command(builddep)' autoconf213 git make which llvm-devel \ + xz clang llvm rust RUN dnf -y builddep ${MOZJS_BUILDDEPS} WORKDIR /root @@ -31,7 +21,6 @@ WORKDIR /root/mozjs/_build -ENV PYTHON3=/usr/bin/python3.9 RUN ../js/src/configure --prefix=/usr --libdir=/usr/lib64 --disable-jemalloc \ --with-system-zlib --with-intl-api ${BUILD_OPTS} RUN make -j$(nproc) @@ -40,9 +29,8 @@ # === Actual Docker image === -FROM registry.fedoraproject.org/fedora:36 +FROM registry.fedoraproject.org/fedora:34 -ARG LOCALES=tr_TR ENV SHELL=/bin/bash # List is comprised of base dependencies for CI scripts, gjs, and debug packages @@ -51,49 +39,15 @@ # Do everything in one RUN command so that the dnf cache is not cached in the # final Docker image. RUN dnf -y install --enablerepo=fedora-debuginfo,updates-debuginfo \ - binutils \ - cairo-debuginfo \ - cairo-debugsource \ - cairo-gobject-devel \ - clang \ - compiler-rt \ - dbus-daemon \ - dbus-x11 \ - diffutils \ - fontconfig-debuginfo \ - fontconfig-debugsource \ - gcc-c++ \ - git \ - glib2-debuginfo \ - glib2-debugsource \ - glib2-devel \ - glibc-debuginfo \ - glibc-gconv-extra \ - glibc-locale-source \ - gnome-desktop-testing \ - gobject-introspection-debuginfo \ - gobject-introspection-debugsource \ - gobject-introspection-devel \ - gtk3-debuginfo \ - gtk3-debugsource \ - gtk3-devel \ - gtk4-debuginfo \ - gtk4-debugsource \ - gtk4-devel \ - lcov \ - libasan \ - libubsan \ - libtsan \ - meson \ - ninja-build \ - pkgconf \ - readline-devel \ - systemtap-sdt-devel \ - valgrind \ - which \ - Xvfb \ - xz \ - && \ + binutils cairo-debuginfo cairo-debugsource cairo-gobject-devel clang \ + compiler-rt dbus-daemon dbus-x11 diffutils fontconfig-debuginfo \ + fontconfig-debugsource gcc-c++ git glib2-debuginfo glib2-debugsource \ + glib2-devel glibc-debuginfo glibc-debuginfo-common gnome-desktop-testing \ + gobject-introspection-debuginfo gobject-introspection-debugsource \ + gobject-introspection-devel gtk3-debuginfo gtk3-debugsource gtk3-devel \ + gtk4-debuginfo gtk4-debugsource gtk4-devel lcov libasan libubsan libtsan \ + meson ninja-build pkgconf readline-devel systemtap-sdt-devel valgrind \ + which Xvfb xz && \ dnf clean all && rm -rf /var/cache/dnf COPY --from=mozjs-build /root/mozjs-install/usr /usr @@ -105,12 +59,6 @@ ENV HOST_USER_ID 5555 RUN useradd -u $HOST_USER_ID -G wheel -ms /bin/bash user -# Enable locales needed for specific tests -RUN for locale in ${LOCALES}; do \ - localedef --verbose --force -i "$locale" "$locale" || true; \ - localedef --verbose --force -i "$locale" -f UTF-8 "$locale".UTF-8 || true; \ - done - USER user WORKDIR /home/user diff -Nru gjs-1.74.0/test/extra/Dockerfile.debug gjs-1.72.2/test/extra/Dockerfile.debug --- gjs-1.74.0/test/extra/Dockerfile.debug 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/test/extra/Dockerfile.debug 2022-08-08 05:05:12.000000000 +0000 @@ -3,36 +3,23 @@ # === Build stage === -FROM registry.fedoraproject.org/fedora:36 AS build +FROM registry.fedoraproject.org/fedora:34 AS build ARG MOZJS_BRANCH=mozjs91 ARG MOZJS_BUILDDEPS=${MOZJS_BRANCH} ARG BUILD_OPTS= ENV SHELL=/bin/bash -# mozjs91 cannot be built with python3.10 -RUN dnf -y install 'dnf-command(builddep)' \ - autoconf213 \ - clang \ - clang-devel \ - cmake \ - git \ - llvm \ - llvm-devel \ - make \ - ninja-build \ - python3.9 \ - rust \ - which \ - xz +RUN dnf -y install 'dnf-command(builddep)' autoconf213 clang-devel cmake git \ + llvm-devel make ninja-build which xz clang llvm rust RUN dnf -y builddep ${MOZJS_BUILDDEPS} WORKDIR /root RUN mkdir -p include-what-you-use/_build -ADD https://include-what-you-use.org/downloads/include-what-you-use-0.18.src.tar.gz /root/include-what-you-use/ +ADD https://include-what-you-use.org/downloads/include-what-you-use-0.16.src.tar.gz /root/include-what-you-use/ WORKDIR /root/include-what-you-use -RUN tar xzf include-what-you-use-0.18.src.tar.gz --strip-components=1 +RUN tar xzf include-what-you-use-0.16.src.tar.gz --strip-components=1 WORKDIR /root/include-what-you-use/_build @@ -47,7 +34,6 @@ WORKDIR /root/mozjs/_build -ENV PYTHON3=/usr/bin/python3.9 RUN ../js/src/configure --prefix=/usr --libdir=/usr/lib64 --disable-jemalloc \ --with-system-zlib --with-intl-api --enable-debug \ ${BUILD_OPTS} @@ -57,9 +43,8 @@ # === Actual Docker image === -FROM registry.fedoraproject.org/fedora:36 +FROM registry.fedoraproject.org/fedora:34 -ARG LOCALES=tr_TR ENV SHELL=/bin/bash # List is comprised of base dependencies for CI scripts, gjs, and debug packages @@ -68,50 +53,15 @@ # Do everything in one RUN command so that the dnf cache is not cached in the # final Docker image. RUN dnf -y install --enablerepo=fedora-debuginfo,updates-debuginfo \ - binutils \ - cairo-debuginfo \ - cairo-debugsource \ - cairo-gobject-devel \ - clang \ - compiler-rt \ - dbus-daemon \ - dbus-x11 \ - diffutils \ - fontconfig-debuginfo \ - fontconfig-debugsource \ - gcc-c++ \ - git \ - glib2-debuginfo \ - glib2-debugsource \ - glib2-devel \ - glibc-debuginfo \ - glibc-gconv-extra \ - glibc-locale-source \ - gnome-desktop-testing \ - gobject-introspection-debuginfo \ - gobject-introspection-debugsource \ - gobject-introspection-devel \ - gtk3-debuginfo \ - gtk3-debugsource \ - gtk3-devel \ - gtk4-debuginfo \ - gtk4-debugsource \ - gtk4-devel \ - lcov \ - libasan \ - libubsan \ - libtsan \ - meson \ - ninja-build \ - pkgconf \ - readline-devel \ - sysprof-devel \ - systemtap-sdt-devel \ - valgrind \ - which \ - Xvfb \ - xz \ - && \ + binutils cairo-debuginfo cairo-debugsource cairo-gobject-devel clang \ + compiler-rt dbus-daemon dbus-x11 diffutils fontconfig-debuginfo \ + fontconfig-debugsource gcc-c++ git glib2-debuginfo glib2-debugsource \ + glib2-devel glibc-debuginfo glibc-debuginfo-common gnome-desktop-testing \ + gobject-introspection-debuginfo gobject-introspection-debugsource \ + gobject-introspection-devel gtk3-debuginfo gtk3-debugsource gtk3-devel \ + gtk4-debuginfo gtk4-debugsource gtk4-devel lcov libasan libubsan libtsan \ + meson ninja-build pkgconf readline-devel sysprof-devel systemtap-sdt-devel \ + valgrind which Xvfb xz && \ dnf clean all && rm -rf /var/cache/dnf COPY --from=build /root/mozjs-install/usr /usr @@ -125,12 +75,6 @@ ENV HOST_USER_ID 5555 RUN useradd -u $HOST_USER_ID -G wheel -ms /bin/bash user -# Enable locales needed for specific tests -RUN for locale in ${LOCALES}; do \ - localedef --verbose --force -i "$locale" "$locale" || true; \ - localedef --verbose --force -i "$locale" -f UTF-8 "$locale".UTF-8 || true; \ - done - USER user WORKDIR /home/user diff -Nru gjs-1.74.0/test/gjs-test-call-args.cpp gjs-1.72.2/test/gjs-test-call-args.cpp --- gjs-1.74.0/test/gjs-test-call-args.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/test/gjs-test-call-args.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -11,13 +11,13 @@ #include #include #include -#include #include #include #include #include #include #include // for UniqueChars +#include // for JS_DefineFunctions #include "gjs/jsapi-util-args.h" #include "gjs/jsapi-util.h" diff -Nru gjs-1.74.0/test/gjs-test-rooting.cpp gjs-1.72.2/test/gjs-test-rooting.cpp --- gjs-1.74.0/test/gjs-test-rooting.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/test/gjs-test-rooting.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -3,13 +3,12 @@ #include -#include // for size_t - #include #include #include // for JS_GC, JS_SetGCCallback, JSGCStatus #include +#include #include #include #include // for JS_NewObject @@ -18,8 +17,6 @@ #include "gjs/jsapi-util-root.h" #include "test/gjs-test-utils.h" -class JSTracer; - // COMPAT: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1553 #ifdef __clang_analyzer__ void g_assertion_message(const char*, const char*, int, const char*, @@ -30,9 +27,6 @@ static GCond gc_finished; static int gc_counter; -// TestObj reserved slots -static const size_t POINTER = 0; - #define PARENT(fx) ((GjsUnitTestFixture *)fx) struct GjsRootingFixture { GjsUnitTestFixture parent; @@ -43,8 +37,8 @@ GjsMaybeOwned *obj; /* only used in callback test cases */ }; -static void test_obj_finalize(JS::GCContext*, JSObject* obj) { - bool* finalized_p = JS::GetMaybePtrFromReservedSlot(obj, POINTER); +static void test_obj_finalize(JSFreeOp*, JSObject* obj) { + bool* finalized_p = static_cast(JS::GetPrivate(obj)); g_assert_false(*finalized_p); *finalized_p = true; } @@ -59,14 +53,16 @@ test_obj_finalize}; static JSClass test_obj_class = { - "TestObj", JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE, - &test_obj_class_ops}; + "TestObj", + JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE, + &test_obj_class_ops +}; static JSObject * test_obj_new(GjsRootingFixture *fx) { JSObject *retval = JS_NewObject(PARENT(fx)->cx, &test_obj_class); - JS::SetReservedSlot(retval, POINTER, JS::PrivateValue(&fx->finalized)); + JS::SetPrivate(retval, &fx->finalized); return retval; } @@ -149,10 +145,10 @@ delete obj; } -static void update_weak_pointer(JSTracer* trc, JS::Compartment*, void* data) { +static void update_weak_pointer(JSContext*, JS::Compartment*, void* data) { auto* obj = static_cast*>(data); if (*obj) - obj->update_after_gc(trc); + obj->update_after_gc(); } static void test_maybe_owned_weak_pointer_is_collected_by_gc( diff -Nru gjs-1.74.0/test/gjs-tests.cpp gjs-1.72.2/test/gjs-tests.cpp --- gjs-1.74.0/test/gjs-tests.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/test/gjs-tests.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -17,17 +17,18 @@ #include #include // for g_unlink +#include #include #include #include #include -#include #include #include #include #include // for UniqueChars #include -#include // for JS_GetClassObject +#include +#include #include // for JSProto_Number #include // for MakeStringSpan @@ -74,9 +75,6 @@ } else if constexpr (std::is_pointer_v) { return reinterpret_cast(get_random_number()); } - - // COMPAT: Work around cppcheck bug https://trac.cppcheck.net/ticket/10731 - g_assert_not_reached(); } static void @@ -689,6 +687,44 @@ g_free(chars); } +static void test_jsapi_util_debug_string_valid_utf8(GjsUnitTestFixture* fx, + const void*) { + JS::RootedValue v_string(fx->cx); + g_assert_true(gjs_string_from_utf8(fx->cx, VALID_UTF8_STRING, &v_string)); + + std::string debug_output = gjs_value_debug_string(fx->cx, v_string); + + g_assert_cmpstr("\"" VALID_UTF8_STRING "\"", ==, debug_output.c_str()); +} + +static void test_jsapi_util_debug_string_invalid_utf8(GjsUnitTestFixture* fx, + const void*) { + g_test_skip("SpiderMonkey doesn't validate UTF-8 after encoding it"); + + JS::RootedValue v_string(fx->cx); + const char16_t invalid_unicode[] = { 0xffff, 0xffff }; + v_string.setString(JS_NewUCStringCopyN(fx->cx, invalid_unicode, 2)); + + std::string debug_output = gjs_value_debug_string(fx->cx, v_string); + // g_assert_cmpstr("\"\\xff\\xff\\xff\\xff\"", ==, debug_output.c_str()); +} + +static void test_jsapi_util_debug_string_object_with_complicated_to_string( + GjsUnitTestFixture* fx, const void*) { + const char16_t desserts[] = { + 0xd83c, 0xdf6a, /* cookie */ + 0xd83c, 0xdf69, /* doughnut */ + }; + JS::RootedValueArray<2> contents(fx->cx); + contents[0].setString(JS_NewUCStringCopyN(fx->cx, desserts, 2)); + contents[1].setString(JS_NewUCStringCopyN(fx->cx, desserts + 2, 2)); + JS::RootedObject array(fx->cx, JS::NewArrayObject(fx->cx, contents)); + JS::RootedValue v_array(fx->cx, JS::ObjectValue(*array)); + std::string debug_output = gjs_value_debug_string(fx->cx, v_array); + + g_assert_cmpstr(u8"🍪,🍩", ==, debug_output.c_str()); +} + static void test_gjs_debug_id_string_no_quotes(GjsUnitTestFixture* fx, const void*) { jsid id = gjs_intern_string_to_id(fx->cx, "prop_key"); @@ -1128,6 +1164,12 @@ test_jsapi_util_string_char16_data); ADD_JSAPI_UTIL_TEST("string/to_ucs4", test_jsapi_util_string_to_ucs4); + ADD_JSAPI_UTIL_TEST("debug_string/valid-utf8", + test_jsapi_util_debug_string_valid_utf8); + ADD_JSAPI_UTIL_TEST("debug_string/invalid-utf8", + test_jsapi_util_debug_string_invalid_utf8); + ADD_JSAPI_UTIL_TEST("debug_string/object-with-complicated-to-string", + test_jsapi_util_debug_string_object_with_complicated_to_string); ADD_JSAPI_UTIL_TEST("gi/args/safe-integer/max", gjstest_test_safe_integer_max); diff -Nru gjs-1.74.0/test/gjs-test-utils.h gjs-1.72.2/test/gjs-test-utils.h --- gjs-1.74.0/test/gjs-test-utils.h 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/test/gjs-test-utils.h 2022-08-08 05:05:12.000000000 +0000 @@ -10,10 +10,11 @@ #include // for g_assert_... #include // for uintptr_t +#include // for pair #include // for numeric_limits #include #include // for is_same -#include +#include // IWYU pragma: keep #include "gjs/context.h" diff -Nru gjs-1.74.0/test/test-ci.sh gjs-1.72.2/test/test-ci.sh --- gjs-1.74.0/test/test-ci.sh 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/test/test-ci.sh 2022-08-08 05:05:12.000000000 +0000 @@ -25,11 +25,6 @@ echo '-----------------------------------------' echo 'Finding common ancestor' - if git show-branch ci-upstream-base 2> /dev/null; then - echo "Already found" - return - fi - # We need to add a new remote for the upstream target branch, since this # script could be running in a personal fork of the repository which has out # of date branches. @@ -39,8 +34,6 @@ # should probably be rebased. git remote add upstream https://gitlab.gnome.org/GNOME/gjs.git || \ git remote set-url upstream https://gitlab.gnome.org/GNOME/gjs.git - # $CI_MERGE_REQUEST_TARGET_BRANCH_NAME is only defined if we’re running in a - # merge request pipeline; fall back to $CI_DEFAULT_BRANCH otherwise. base_branch="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}" if ! git fetch --shallow-since="28 days ago" --no-tags upstream "$base_branch"; then echo "Main branch doesn't have history in the past 28 days, fetching " @@ -53,6 +46,9 @@ # Work out the newest common ancestor between the detached HEAD that this CI # job has checked out, and the upstream target branch (which will typically # be `upstream/master` or `upstream/gnome-nn`). + # + # $CI_MERGE_REQUEST_TARGET_BRANCH_NAME is only defined if we’re running in a + # merge request pipeline; fall back to $CI_DEFAULT_BRANCH otherwise. newest_common_ancestor_sha=$(git merge-base ci-upstream-base-branch HEAD) if test -z "$newest_common_ancestor_sha"; then echo "Couldn’t find common ancestor with the upstream main branch. This" @@ -138,7 +134,7 @@ do_Set_Env DEFAULT_CONFIG_OPTS="-Dcairo=enabled -Dreadline=enabled -Dprofiler=enabled \ - -Ddtrace=false -Dsystemtap=false -Dverbose_logs=false" + -Ddtrace=false -Dsystemtap=false -Dverbose_logs=false --werror" meson _build $DEFAULT_CONFIG_OPTS $CONFIG_OPTS ninja -C _build diff -Nru gjs-1.74.0/tools/cppcheck.cfg gjs-1.72.2/tools/cppcheck.cfg --- gjs-1.74.0/tools/cppcheck.cfg 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/tools/cppcheck.cfg 2022-08-08 05:05:12.000000000 +0000 @@ -4,7 +4,6 @@ - diff -Nru gjs-1.74.0/tools/gjs-private-iwyu.imp gjs-1.72.2/tools/gjs-private-iwyu.imp --- gjs-1.74.0/tools/gjs-private-iwyu.imp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/tools/gjs-private-iwyu.imp 2022-08-08 05:05:12.000000000 +0000 @@ -3,12 +3,7 @@ # IWYU mapping file for files that are part of libgjs [ - {"include": ["", "private", "", "public"]}, {"include": ["", "private", "", "public"]}, - {"include": ["", "private", "", "public"]}, - {"include": ["", "private", "", "public"]}, - {"include": ["", "private", "", "public"]}, - {"include": ["", "private", "", "public"]}, {"include": ["", "private", "", "public"]}, {"include": ["", "private", "", "public"]}, {"include": ["", "private", "", "public"]}, @@ -17,41 +12,7 @@ {"include": ["@", "private", "", "public"]}, {"include": ["@\"gio/.*\"", "private", "", "public"]}, {"include": ["@", "private", "", "public"]}, - {"include": ["\"gitypes.h\"", "private", "", "public"]}, - {"include": ["", "private", "", "public"]}, - {"include": ["\"giversion.h\"", "private", "", "public"]}, - {"include": ["@\"gi.*info.h\"", "private", "", "public"]}, - {"include": ["\"glib/galloca.h\"", "private", "", "public"]}, - {"include": ["\"glib/garray.h\"", "private", "", "public"]}, - {"include": ["\"glib/gbacktrace.h\"", "private", "", "public"]}, - {"include": ["\"glib/gbytes.h\"", "private", "", "public"]}, - {"include": ["\"glib/gconvert.h\"", "private", "", "public"]}, - {"include": ["\"glib/genviron.h\"", "private", "", "public"]}, - {"include": ["\"glib/gerror.h\"", "private", "", "public"]}, - {"include": ["\"glib/gfileutils.h\"", "private", "", "public"]}, - {"include": ["\"glib/ghash.h\"", "private", "", "public"]}, - {"include": ["\"glib/glist.h\"", "private", "", "public"]}, - {"include": ["\"glib/gmacros.h\"", "private", "", "public"]}, - {"include": ["\"glib/gmain.h\"", "private", "", "public"]}, - {"include": ["\"glib/gmem.h\"", "private", "", "public"]}, - {"include": ["\"glib/gmessages.h\"", "private", "", "public"]}, - {"include": ["\"glib/gquark.h\"", "private", "", "public"]}, - {"include": ["\"glib/grcbox.h\"", "private", "", "public"]}, - {"include": ["\"glib/grefcount.h\"", "private", "", "public"]}, - {"include": ["\"glib/gslist.h\"", "private", "", "public"]}, - {"include": ["\"glib/gstrfuncs.h\"", "private", "", "public"]}, - {"include": ["\"glib/gstring.h\"", "private", "", "public"]}, - {"include": ["\"glib/gtestutils.h\"", "private", "", "public"]}, - {"include": ["\"glib/gthread.h\"", "private", "", "public"]}, - {"include": ["\"glib/gtimer.h\"", "private", "", "public"]}, - {"include": ["\"glib/gtypes.h\"", "private", "", "public"]}, {"include": ["", "private", "", "public"]}, - {"include": ["\"glib/gunicode.h\"", "private", "", "public"]}, - {"include": ["\"glib/guri.h\"", "private", "", "public"]}, - {"include": ["\"glib/gutils.h\"", "private", "", "public"]}, - {"include": ["\"glib/gvariant.h\"", "private", "", "public"]}, - {"include": ["\"glib/gversion.h\"", "private", "", "public"]}, - {"include": ["\"glibconfig.h\"", "private", "", "public"]}, {"include": ["@\"gobject/.*\"", "private", "", "public"]}, {"include": ["@", "private", "", "public"]}, {"include": ["", "private", "", "public"]}, diff -Nru gjs-1.74.0/tools/process_iwyu.py gjs-1.72.2/tools/process_iwyu.py --- gjs-1.74.0/tools/process_iwyu.py 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/tools/process_iwyu.py 2022-08-08 05:05:12.000000000 +0000 @@ -40,12 +40,12 @@ 'struct JSContext;', 'struct JSClass;', 'class JSFunction;', + 'class JSFreeOp;', 'class JSObject;', 'struct JSRuntime;', 'class JSScript;', 'class JSString;', - 'namespace js { class TempAllocPolicy; }', - 'namespace JS { class GCContext; }', + 'namespace js { class TempAllocPolicy; }' 'namespace JS { struct PropertyKey; }', 'namespace JS { class Symbol; }', 'namespace JS { class BigInt; }', @@ -70,15 +70,22 @@ # std::vector::push_back() # https://github.com/include-what-you-use/include-what-you-use/issues/908 ('gi/function.cpp', '#include ', 'for max'), - ('gi/function.cpp', '#include ', 'for fill_n, max'), # also! ('gi/private.cpp', '#include ', 'for max'), - ('gjs/context.cpp', '#include ', 'for copy, max, find'), ('gjs/importer.cpp', '#include ', 'for max'), - ('gjs/importer.cpp', '#include ', 'for max, copy'), # also! ('modules/cairo-context.cpp', '#include ', 'for max'), + # False positive when using Mozilla vectors' append() and + # infallibleAppend() + # https://github.com/include-what-you-use/include-what-you-use/issues/926 + # https://bugzilla.mozilla.org/show_bug.cgi?id=1713550 + ('gi/function.cpp', '#include ', 'for forward'), + ('gi/ns.cpp', '#include ', 'for forward'), + ('gjs/module.cpp', '#include ', 'for forward'), + ('gjs/objectbox.cpp', '#include ', 'for forward'), + # False positive when using EnumType operators # https://github.com/include-what-you-use/include-what-you-use/issues/927 + ('gi/arg-cache.h', '#include ', 'for enable_if_t'), ('modules/cairo-context.cpp', '#include ', 'for enable_if_t'), ('modules/cairo-region.cpp', '#include ', 'for enable_if_t'), ('modules/cairo-surface.cpp', '#include ', 'for enable_if_t'), @@ -88,6 +95,8 @@ ('gi/boxed.cpp', '#include ', 'for remove_reference<>::type'), ('gi/interface.cpp', '#include ', 'for remove_reference<>::type'), + ('gi/object.cpp', '#include ', + 'for remove_reference<>::type'), ('gi/private.cpp', '#include ', 'for remove_reference<>::type'), ('gi/value.cpp', '#include ', 'for remove_reference<>::type'), @@ -99,30 +108,13 @@ 'for remove_reference<>::type'), ('gjs/profiler.cpp', '#include ', 'for remove_reference<>::type'), + ('gjs/promise.cpp', '#include ', + 'for remove_reference<>::type'), ('test/gjs-test-jsapi-utils.cpp', '#include ', 'for remove_reference<>::type'), - # False positive when constructing JS::GCHashMap - ('gi/boxed.h', '#include ', 'for move'), - ('gi/object.h', '#include ', 'for move'), - ('gjs/jsapi-util-error.cpp', '#include ', 'for move'), - ('gjs/jsapi-util-error.h', '#include ', 'for move'), - - # Haven't managed to diagnose this one. It's triggered by replacing log.cpp - # with the following code, but not by that code in a standalone file. - # #include - # static std::vector v; - # void f() { v = std::vector(1, true); } - ('util/log.cpp', '#include ', 'for copy'), - - # For some reason IWYU wants these with angle brackets when they are - # already present with quotes - # https://github.com/include-what-you-use/include-what-you-use/issues/1087 - ('gjs/context.cpp', '#include ', ''), - ('gjs/coverage.cpp', '#include ', ''), - ('gjs/error-types.cpp', '#include ', ''), - ('gjs/jsapi-util.cpp', '#include ', ''), - ('gjs/mem.cpp', '#include ', ''), + # Weird false positive on some versions of IWYU + ('gi/arg.cpp', 'struct _GVariant;', ''), ('gjs/profiler.cpp', '#include ', ''), ) diff -Nru gjs-1.74.0/tools/run_iwyu.sh gjs-1.72.2/tools/run_iwyu.sh --- gjs-1.74.0/tools/run_iwyu.sh 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/tools/run_iwyu.sh 2022-08-08 05:05:12.000000000 +0000 @@ -44,10 +44,9 @@ echo "files: $files" IWYU="python3 $(which iwyu_tool || which iwyu-tool || which iwyu_tool.py) -p ." -IWYU_TOOL_ARGS="-I../gjs" IWYU_ARGS="-Wno-pragma-once-outside-header" IWYU_RAW="include-what-you-use -xc++ -std=c++17 -Xiwyu --keep=config.h $IWYU_ARGS" -IWYU_RAW_INC="-I. -I.. $(pkg-config --cflags gobject-introspection-1.0 mozjs-102)" +IWYU_RAW_INC="-I. -I.. $(pkg-config --cflags gobject-introspection-1.0 mozjs-91)" PRIVATE_MAPPING="-Xiwyu --mapping_file=$SRCDIR/tools/gjs-private-iwyu.imp -Xiwyu --keep=config.h" PUBLIC_MAPPING="-Xiwyu --mapping_file=$SRCDIR/tools/gjs-public-iwyu.imp" POSTPROCESS="python3 $SRCDIR/tools/process_iwyu.py" @@ -70,19 +69,17 @@ for FILE in $SRCDIR/gi/*.cpp $SRCDIR/gjs/atoms.cpp $SRCDIR/gjs/byteArray.cpp \ $SRCDIR/gjs/coverage.cpp $SRCDIR/gjs/debugger.cpp \ - $SRCDIR/gjs/deprecation.cpp $SRCDIR/gjs/engine.cpp \ - $SRCDIR/gjs/error-types.cpp $SRCDIR/gjs/global.cpp \ - $SRCDIR/gjs/internal.cpp $SRCDIR/gjs/importer.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/mainloop.cpp \ $SRCDIR/gjs/module.cpp $SRCDIR/gjs/native.cpp \ $SRCDIR/gjs/objectbox.cpp $SRCDIR/gjs/promise.cpp $SRCDIR/gjs/stack.cpp \ - $SRCDIR/gjs/text-encoding.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/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 $IWYU_TOOL_ARGS | $POSTPROCESS; then + if ! $IWYU $FILE -- $PRIVATE_MAPPING | $POSTPROCESS; then EXIT=1 fi fi @@ -92,7 +89,6 @@ if ( should_analyze $SRCDIR/gjs/jsapi-dynamic-class.cpp || \ should_analyze $SRCDIR/gjs/jsapi-class.h ); then if ! $IWYU $SRCDIR/gjs/jsapi-dynamic-class.cpp -- $PRIVATE_MAPPING \ - $IWYU_TOOL_ARGS \ -Xiwyu --check_also=*/gjs/jsapi-class.h | $POSTPROCESS; then EXIT=1 fi @@ -101,7 +97,7 @@ # include header files with private implementation along with their main files for STEM in gjs/context gjs/mem gjs/profiler modules/cairo; do if should_analyze $SRCDIR/$STEM.cpp; then - if ! $IWYU $SRCDIR/$STEM.cpp -- $PRIVATE_MAPPING $IWYU_TOOL_ARGS \ + if ! $IWYU $SRCDIR/$STEM.cpp -- $PRIVATE_MAPPING \ -Xiwyu --check_also=*/$STEM-private.h | $POSTPROCESS; then EXIT=1 fi @@ -111,7 +107,7 @@ for FILE in $SRCDIR/gjs/console.cpp $SRCDIR/installed-tests/minijasmine.cpp do if should_analyze $FILE; then - if ! $IWYU $FILE -- $PUBLIC_MAPPING $IWYU_TOOL_ARGS | $POSTPROCESS; then + if ! $IWYU $FILE -- $PUBLIC_MAPPING | $POSTPROCESS; then EXIT=1 fi fi diff -Nru gjs-1.74.0/util/log.cpp gjs-1.72.2/util/log.cpp --- gjs-1.74.0/util/log.cpp 2022-09-21 03:19:18.000000000 +0000 +++ gjs-1.72.2/util/log.cpp 2022-08-08 05:05:12.000000000 +0000 @@ -8,7 +8,6 @@ #include // for remove_reference<>::type #include -#include // for SEEK_END #include #include // for FILE, fprintf, fflush, fopen, fputs, fseek #include // for strchr, strcmp