diff options
author | Philip Chimento <philip.chimento@gmail.com> | 2022-08-28 01:03:20 +0000 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2022-08-28 01:03:20 +0000 |
commit | 5719874a7551aa5fcf7a96e35b4fe9828440d2fc (patch) | |
tree | 0dc4a979ff269281160b49813b36108f232cc069 | |
parent | e86716d8129156f56d1b0418de8bc9bf0adb5c43 (diff) | |
parent | f81bccefe156dd5453b35bee025b58d6176ff4fc (diff) | |
download | gjs-5719874a7551aa5fcf7a96e35b4fe9828440d2fc.tar.gz |
Merge branch 'wip/andyholmes/devdocs-scraper' into 'master'
doc: reformat for better scraping with DevDocs
See merge request GNOME/gjs!792
-rw-r--r-- | doc/ByteArray.md | 118 | ||||
-rw-r--r-- | doc/Console.md | 314 | ||||
-rw-r--r-- | doc/ESModules.md | 2 | ||||
-rw-r--r-- | doc/Encoding.md | 152 | ||||
-rw-r--r-- | doc/Environment.md | 10 | ||||
-rw-r--r-- | doc/Format.md | 123 | ||||
-rw-r--r-- | doc/Gettext.md | 233 | ||||
-rw-r--r-- | doc/Home.md | 87 | ||||
-rw-r--r-- | doc/Lang.md | 141 | ||||
-rw-r--r-- | doc/Logging.md | 167 | ||||
-rw-r--r-- | doc/Mainloop.md | 213 | ||||
-rw-r--r-- | doc/Mapping.md | 280 | ||||
-rw-r--r-- | doc/Modules.md | 384 | ||||
-rw-r--r-- | doc/Overrides.md | 806 | ||||
-rw-r--r-- | doc/Profiling.md | 6 | ||||
-rw-r--r-- | doc/README.md | 104 | ||||
-rw-r--r-- | doc/Signals.md | 103 | ||||
-rw-r--r-- | doc/System.md | 262 | ||||
-rw-r--r-- | doc/Testing.md | 23 | ||||
-rw-r--r-- | doc/Timers.md | 77 | ||||
-rw-r--r-- | doc/cairo.md | 140 |
21 files changed, 3046 insertions, 699 deletions
diff --git a/doc/ByteArray.md b/doc/ByteArray.md index d1c5bd3e..41394d7c 100644 --- a/doc/ByteArray.md +++ b/doc/ByteArray.md @@ -1,59 +1,117 @@ -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`. +# ByteArray -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 -### `fromString(s:String, encoding:String):Uint8Array` ### +#### 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 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). -**DEPRECATED** +[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 -Use `new TextEncoder(encoding).encode(string)` instead. +Parameters: +* byteArray (`Uint8Array`) — A byte array to decode +* encoding (`String`) — Optional encoding of `byteArray` -### `toString(a:Uint8Array, encoding:String):String` ### +Returns: +* (`String`) — A 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()`, i.e., `b === ByteArray.fromString(ByteArray.toString(b, encoding), encoding)`. +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: -**DEPRECATED** +```js +const original = ByteArray.fromString('foobar'); +const copy = ByteArray.fromString(ByteArray.toString(original)); -Use `new TextDecoder(encoding).decode(string)` instead. +console.assert(original.every((value, index) => value === copy[index])); +``` -### `fromGBytes(b:GLib.Bytes):Uint8Array` ### +[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`. -Convert a `GLib.Bytes` instance into a newly constructed `Uint8Array`. The contents are copied. -**DEPRECATED** +[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 -Use `GLib.Bytes.prototype.toArray` instead. +Returns: +* (`GLib.Bytes`) — A new [`GLib.Bytes`][gbytes] -### `toGBytes(a:Uint8Array):GLib.Bytes` ### +Converts the `Uint8Array` into a [`GLib.Bytes`][gbytes] instance. -Converts the `Uint8Array` into a `GLib.Bytes` instance. The contents are copied. -**DEPRECATED** +[gbytes]: https://gjs-docs.gnome.org/glib20/glib.bytes -Use `new GLib.Bytes(a:Uint8Array)` instead. diff --git a/doc/Console.md b/doc/Console.md new file mode 100644 index 00000000..2336e3a8 --- /dev/null +++ b/doc/Console.md @@ -0,0 +1,314 @@ +# 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 --git a/doc/ESModules.md b/doc/ESModules.md index 1807d3d9..4c3f0f47 100644 --- a/doc/ESModules.md +++ b/doc/ESModules.md @@ -1,4 +1,4 @@ -# Modules: ECMAScript 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._ diff --git a/doc/Encoding.md b/doc/Encoding.md new file mode 100644 index 00000000..38011362 --- /dev/null +++ b/doc/Encoding.md @@ -0,0 +1,152 @@ +# 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 --git a/doc/Environment.md b/doc/Environment.md index 84a6ecb0..143db197 100644 --- a/doc/Environment.md +++ b/doc/Environment.md @@ -1,8 +1,8 @@ -## Environment +# Environment GJS allows runtime configuration with a number of environment variables. -### General +## General * `GJS_PATH` @@ -17,7 +17,7 @@ GJS allows runtime configuration with a number of environment variables. 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 @@ GJS allows runtime configuration with a number of environment variables. JavaScript engine. -### Debugging +## Debugging * `GJS_DEBUG_HEAP_OUTPUT` @@ -75,7 +75,7 @@ GJS allows runtime configuration with a number of environment variables. Set this variable to print a timestamp when logging. -### Testing +## Testing * `GJS_COVERAGE_OUTPUT` diff --git a/doc/Format.md b/doc/Format.md new file mode 100644 index 00000000..97371e65 --- /dev/null +++ b/doc/Format.md @@ -0,0 +1,123 @@ +# 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 --git a/doc/Gettext.md b/doc/Gettext.md new file mode 100644 index 00000000..05127304 --- /dev/null +++ b/doc/Gettext.md @@ -0,0 +1,233 @@ +# 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 --git a/doc/Home.md b/doc/Home.md index ec39d949..7dd80797 100644 --- a/doc/Home.md +++ b/doc/Home.md @@ -1,89 +1,4 @@ # GJS: Javascript Bindings for GNOME -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. +This page has moved to [`README.md`](README.md). -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 - -## 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. - -Additional GJS documentation can be found under [doc](.). - -[GJS Guide](gjs-guide) contains tutorials for begineers. - -[GTK4 + GJS Book](https://rmnvgr.gitlab.io/gtk4-gjs-book/) is a start to finish walkthrough for the creation of GTK4 + GJS applications. - -The main [GNOME developer portal][gnome-developer] contains numerous examples in JavaScript for GJS. - -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 -[gjs-guide]: https://gjs.guide/ -[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] 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 repository]: 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) - -## 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 --git a/doc/Lang.md b/doc/Lang.md new file mode 100644 index 00000000..9056eee3 --- /dev/null +++ b/doc/Lang.md @@ -0,0 +1,141 @@ +# 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 --git a/doc/Logging.md b/doc/Logging.md index f72be9cc..c7139b83 100644 --- a/doc/Logging.md +++ b/doc/Logging.md @@ -1,124 +1,121 @@ +# 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. -## `console` Functions +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. -As of GJS 1.70 (GNOME 41), the `console` collection of functions are available -as described in the WHATWG [Console Standard][console-standard]. The `console` -object is available globally (i.e. without import) and the implementation source -is found in [console.js][console-js]. +[console]: https://gjs-docs.gnome.org/gjs/console.md -## Built-in Functions +### log(message) -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]. +> See also: [`console.log()`][console-log] -### log() +Type: +* Static -`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. +Parameters: +* message (`Any`) — A string or any coercible value + +Logs a message with severity equal to +[`GLib.LogLevelFlags.LEVEL_MESSAGE`][gloglevelflagsmessage]. ```js // expected output: JS LOG: Some message log('Some message'); // expected output: JS LOG: [object Object] -log(new Object()); +log({key: 'value'}); ``` -### logError() +[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) -`logError()` is a more useful function for debugging that logs the stack trace of -a JavaScript `Error()` object, with an optional prefix. +> See also: [`console.trace()`][console-trace] -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: +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]. + +This function is commonly used in conjunction with `try...catch` blocks to log +errors while still trapping the exception: ```js -$ 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 -@<stdin>:1:34 +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: -### print() & printerr() +```js +Promise.reject().catch(logError); +``` + +[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()` 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()`. +Parameters: +* messages (`Any`) — Any number of strings or coercible values -`printerr()` is exactly like `print()`, except the resulting message is printed -to `stderr` with `g_printerr()`. +Takes any number of strings (or values that can be coerced to strings), joins +them with a space and appends a newline character (`\n`). -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. +The resulting string is printed directly to `stdout` of the current process with +[`g_print()`][gprint]. ```js -$ gjs -gjs> print('some', 'string', 42); -some string 42$ -gjs> printerr('some text 42'); -some text +$ gjs -c "print('foobar', 42, {});" +foobar 42 [object Object] +$ ``` +[gprint]: https://docs.gtk.org/glib/func.print.html -# GLib Functions +### printerr(...messages) -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. +> Note: this function is not useful for GNOME Shell extensions -Below is a common pattern for defining a series of logging functions as used in -[Polari][polari] and some other GJS applications: +Type: +* Static -```js -const GLib = imports.gi.GLib; - -var LOG_DOMAIN = 'Polari'; - -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 - }); - }; -} +Parameters: +* messages (`Any`) — Any number of strings or coercible values -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); +Takes any number of strings (or values that can be coerced to strings), joins +them with a space and appends a newline character (`\n`). -// Log all messages when connected to the journal -if (GLib.log_writer_is_journald(2)) - GLib.setenv('G_MESSAGES_DEBUG', LOG_DOMAIN, false); +The resulting string is printed directly to `stderr` of the current process with +[`g_printerr()`][gprinterr]. + +```js +$ gjs -c "printerr('foobar', 42, {});" +foobar 42 [object Object] +$ ``` -[console-js]: https://gitlab.gnome.org/GNOME/gjs/-/blob/HEAD/modules/esm/console.js -[console-standard]: https://console.spec.whatwg.org/ -[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 +[gprinterr]: https://docs.gtk.org/glib/func.printerr.html diff --git a/doc/Mainloop.md b/doc/Mainloop.md new file mode 100644 index 00000000..729f1d24 --- /dev/null +++ b/doc/Mainloop.md @@ -0,0 +1,213 @@ +# 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 --git a/doc/Mapping.md b/doc/Mapping.md index e635a667..5f2d24a0 100644 --- a/doc/Mapping.md +++ b/doc/Mapping.md @@ -1,32 +1,48 @@ -## GObject Construction, Subclassing, Templates and GType +# GObject Usage in GJS -### Constructing GObjects +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. -GObjects can be constructed with the `new` operator, just like JavaScript objects, and usually take an Object map of properties. +## GObject Construction -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. +GObjects can be constructed with the `new` operator, and usually take an `Object` map of properties: ```js -let label = new Gtk.Label({ +const label = new Gtk.Label({ label: '<a href="https://www.gnome.org">gnome.org</a>', 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()`: -let file = Gio.File.new_for_path('/proc/cpuinfo'); +```js +const 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/ -### Subclassing GObjects +## GObject Subclassing + +> See also: [`GObject.registerClass()`](overrides.md#gobject-registerclass) -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({ @@ -48,63 +64,41 @@ var MyLabel = GObject.registerClass({ }); ``` -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. +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()`. -### GType Objects +For a more complete introduction to GObject subclassing in GJS, see the +[GObject Tutorial][gobject-subclassing]. -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-subclassing]: https://gjs.guide/guides/gobject/subclassing.html#subclassing-gobject -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 -```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. +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.name); -log(labelInstance.constructor.$gtype.name); -// expected output: GtkLabel +let value; -log(MyLabel.$gtype.name); -// expected output: Gjs_MyLabel -``` +value = label.use_markup; +value = label.get_use_markup(); +value = label['use-markup']; -[`instanceof`][mdn-instanceof] can be used to compare an object instance to a **constructor object**. +label.use_markup = value; +label.set_use_markup(value); +label['use-markup'] = value; -```js -log(typeof labelInstance); -// expected output: object - -log(labelInstance instanceof Gtk.Label); -// expected output: true +label.connect('notify::use-markup', () => {}); ``` -[mdn-instanceof]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/instanceof +GObject subclasses can register properties, which is necessary if you want to +use `GObject.notify()` or `GObject.bind_property()`. -## 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. +> Warning: Never use underscores in property names in the ParamSpec, because of +> the conversion between underscores and hyphens mentioned above. ```js var MyLabel = GObject.registerClass({ @@ -133,28 +127,37 @@ var MyLabel = GObject.registerClass({ }); ``` -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). +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. -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. +## GObject Signals -## Signals +> See also: The [`Signals`][signals-module] module contains an GObject-like +> signal framework for native Javascript classes -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); ``` @@ -176,31 +179,90 @@ var MyLabel = GObject.registerClass({ }); ``` -**NOTE:** GJS also includes a built-in [`signals`](Modules#signals) module for applying signals to native JavaScript classes. +[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 ## 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]. +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: ```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 -let myApp = new Gio.Application({ - flags: Gio.ApplicationFlags.HANDLES_OPEN | Gio.ApplicationFlags.HANDLES_COMMAND_LINE +// Setting a flags property with a combination of flags +const myApp = new Gio.Application({ + flags: Gio.ApplicationFlags.HANDLES_OPEN | + Gio.ApplicationFlags.HANDLES_COMMAND_LINE }); -if (myApp.flags & Gio.ApplicationFlags.HANDLES_OPEN) { +// Checking if a flag is set, and removing it if so +if (myApp.flags & Gio.ApplicationFlags.HANDLES_OPEN) myApp.flags &= ~Gio.ApplicationFlags.HANDLES_OPEN; -} ``` [gjs-docs]: https://gjs-docs.gnome.org @@ -208,38 +270,74 @@ if (myApp.flags & Gio.ApplicationFlags.HANDLES_OPEN) { ## Structs and Unions -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. +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: ```js -widget.connect("key-press-event", (widget, event) => { - log(event); +widget.connect('key-press-event', (widget, event) => { // expected output: [union instance proxy GIName:Gdk.Event jsobj@0x7f19a00b6400 native@0x5620c6a7c6e0] - log(event.get_event_type() === Gdk.EventType.KEY_PRESS); + log(event); + // expected output: true - let [ok, keyval] = event.get_keyval(); - log(keyval); + log(event.get_event_type() === Gdk.EventType.KEY_PRESS); + // example output: 65507 + const [, keyval] = event.get_keyval(); + log(keyval); }); ``` [gdk-event]: https://gjs-docs.gnome.org/gdk40/gdk.event -## Multiple return values (caller-allocates) +## 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. -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. +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: ```js -let [minimumSize, naturalSize] = label.get_preferred_size(); +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' }); -// Functions with boolean 'success' returns often still throw an Error on failure + // 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 try { - 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); + const file = new Gio.File({ path: '/proc/cpuinfo' }); + + // Eliding success boolean + const [, contents, etag] = file.load_contents(null); } catch(e) { log('Failed to read file: ' + e.message); } ``` + diff --git a/doc/Modules.md b/doc/Modules.md index 38492271..f4d9c697 100644 --- a/doc/Modules.md +++ b/doc/Modules.md @@ -1,362 +1,24 @@ -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. +# Modules + +The documentation previously found here has been updated and reorganized. Most +of the documentation can now be browsed at https://gjs-docs.gnome.org. + +* [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/) -## [Gio](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/core/overrides/Gio.js) - -**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'; -// or -import Gtk from 'gi://Gtk?version=4.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 #60027][bug-60027]). - -```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)}` - -const Format = imports.format; - -// Using format() (Output: Pi to 2 decimal points: 3.14) -Format.format.call("%s to %d decimal points: %.2f", foo, bar * 2, baz); - -// Applying format() to the string prototype (this is the old way, but -// is often considered bad practice now, especially in GNOME Shell -// extensions where other extensions might overwrite it. -// Consider not doing this!) -String.prototype.format = Format.format; -"%s to %d decimal points: %.2f".format(foo, bar*2, baz); - -// Using format() with Gettext -Format.format.call(_("%d:%d"), 11, 59); -Format.format.call( - 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 -[bug-60027]: https://savannah.gnu.org/bugs/?60027 - -## [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 - - -## [bytearray](https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/modules/system.cpp) - -**DEPRECATED** - -`const byteArray = imports.byteArray;` - -See [ByteArray](ByteArray.md). - -## [Tweener](https://gitlab.gnome.org/GNOME/gjs/-/blob/HEAD/modules/script/tweener/tweener.js) - -**DEPRECATED** - -**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 --git a/doc/Overrides.md b/doc/Overrides.md new file mode 100644 index 00000000..9dfaaed3 --- /dev/null +++ b/doc/Overrides.md @@ -0,0 +1,806 @@ +# 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 `<node>` 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 `<interface>` 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 `<interface>` 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 --git a/doc/Profiling.md b/doc/Profiling.md index e84d3af2..65321f62 100644 --- a/doc/Profiling.md +++ b/doc/Profiling.md @@ -1,6 +1,6 @@ -# Profiling GJS +# Profiling -## Profiling with Sysprof +## Sysprof Typical profiling of JavaScript code is performed by passing the `--gjs` and `--no-perf` options: @@ -22,7 +22,7 @@ Other flags can also be combined with `--gjs` when appropriate: sysprof-cli --gjs --gtk -- gjs gtk.js ``` -### Additional Reading +#### See Also * Christian Hergert's [Blog Posts on Sysprof](https://blogs.gnome.org/chergert/category/sysprof/) diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000..306e7695 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,104 @@ +# 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 --git a/doc/Signals.md b/doc/Signals.md new file mode 100644 index 00000000..dacbf180 --- /dev/null +++ b/doc/Signals.md @@ -0,0 +1,103 @@ +## 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 --git a/doc/System.md b/doc/System.md new file mode 100644 index 00000000..3f51e349 --- /dev/null +++ b/doc/System.md @@ -0,0 +1,262 @@ +# 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 --git a/doc/Testing.md b/doc/Testing.md new file mode 100644 index 00000000..28b18315 --- /dev/null +++ b/doc/Testing.md @@ -0,0 +1,23 @@ +# 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 --git a/doc/Timers.md b/doc/Timers.md new file mode 100644 index 00000000..28008b03 --- /dev/null +++ b/doc/Timers.md @@ -0,0 +1,77 @@ +# 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 --git a/doc/cairo.md b/doc/cairo.md index 6f83dbbe..14fddcef 100644 --- a/doc/cairo.md +++ b/doc/cairo.md @@ -1,43 +1,46 @@ -The cairo bindings follows the C API pretty closely. +# Cairo -## Naming ## +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 module name is called 'cairo' and usually imported into -the namespace as 'Cairo'. -```js -const Cairo = imports.cairo; -``` -Methods are studlyCaps, similar to other JavaScript apis, eg +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_move_to` is wrapped to `Cairo.Context.moveTo()` -`cairo_surface_write_to_png` to `Cairo.Context.writeToPNG()`. +[cairo]: https://www.cairographics.org/ +[cairo-docs]: https://www.cairographics.org/documentation/ -Abbreviations such as RGB, RGBA, PNG, PDF, SVG are always -upper-case. +#### Import -Enums are set in the cairo namespace, the enum names are capitalized: +When using ESModules: -`CAIRO_FORMAT_ARGB32` is mapped to `Cairo.Format.ARGB32` etc. +```js +import Cairo from 'cairo'; +``` -## Surfaces (`cairo_surface_t`) ## +When using legacy imports: -Prototype hierarchy +```js +const Cairo = imports.cairo; +``` -* `Surface` (abstract) - * `ImageSurface` - * `PDFSurface` - * `SVGSurface` - * `PostScriptSurface` +#### Mapping -The native surfaces (win32, quartz, xlib) are not supported at this point. +Methods are studlyCaps, similar to other JavaScript APIs. Abbreviations such as +RGB, RGBA, PNG, PDF and SVG are always upper-case. For example: -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"); -``` +* `cairo_move_to()` is mapped to `Cairo.Context.moveTo()` +* `cairo_surface_write_to_png()` is mapped to `Cairo.Context.writeToPNG()` -## Context (`cairo_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`). + +[cairo-devdocs]: https://gjs-docs.gnome.org/cairo10 + +## Cairo.Context (`cairo_t`) `cairo_t` is mapped as `Cairo.Context`. @@ -49,19 +52,53 @@ let cr = new Cairo.Context(surface); let cr = Gdk.cairo_create(...); ``` + All introspection methods taking or returning a `cairo_t` will automatically create a `Cairo.Context`. -## Patterns (`cairo_pattern_t`) ## +### 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`) Prototype hierarchy -* `Pattern` - * `Gradient` - * `LinearGradient` - * `RadialGradient` - * `SurfacePattern` - * `SolidPattern` +* `Cairo.Pattern` + * `Cairo.Gradient` + * `Cairo.LinearGradient` + * `Cairo.RadialGradient` + * `Cairo.SurfacePattern` + * `Cairo.SolidPattern` You can create a linear gradient by calling the constructor: @@ -77,7 +114,32 @@ let pattern = new Cairo.SolidPattern.createRGB(0, 0, 0); let pattern = new Cairo.SolidPattern.createRGBA(0, 0, 0, 0); ``` -TODO: + +## 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: + * context: wrap the remaining methods * surface methods * image surface methods @@ -85,9 +147,13 @@ TODO: * version * iterating over `cairo_path_t` -Fonts & Glyphs are not wrapped, use PangoCairo instead. +Many font and glyph operations are not yet supported, and it is recommended to +use [`PangoCairo`][pango-cairo] as an alternative: + * glyphs * text cluster * font face * scaled font * font options + +[pango-cairo]: https://gjs-docs.gnome.org/pangocairo10 |