[gjs/esm/static-imports] Finish adding additional libraries/bindings.
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/esm/static-imports] Finish adding additional libraries/bindings.
- Date: Sat, 14 Nov 2020 20:34:31 +0000 (UTC)
commit 71ff942d68497566cb8cd2da369376ca6f1fa559
Author: Evan Welsh <noreply evanwelsh com>
Date: Sat Nov 14 14:34:19 2020 -0600
Finish adding additional libraries/bindings.
js.gresource.xml | 2 +
lib/modules/gi.js | 2 +-
modules/core/_text.js | 13 +++++++
modules/esm/cairo.js | 7 ++++
modules/esm/format.js | 7 +++-
modules/esm/gi.js | 66 +++++++++++++++++++++++++++++++
modules/esm/signals.js | 75 ++++++++++--------------------------
modules/script/_bootstrap/default.js | 13 +++++++
8 files changed, 127 insertions(+), 58 deletions(-)
---
diff --git a/js.gresource.xml b/js.gresource.xml
index 410f17ea..bbd0106d 100644
--- a/js.gresource.xml
+++ b/js.gresource.xml
@@ -9,6 +9,7 @@
<file>lib/entry.js</file>
<!-- ESM-based modules -->
+ <file>modules/esm/cairo.js</file>
<file>modules/esm/gi.js</file>
<file>modules/esm/system.js</file>
<file>modules/esm/format.js</file>
@@ -47,5 +48,6 @@
<file>modules/core/_format.js</file>
<file>modules/core/_gettext.js</file>
<file>modules/core/_signals.js</file>
+ <file>modules/core/_text.js</file>
</gresource>
</gresources>
diff --git a/lib/modules/gi.js b/lib/modules/gi.js
index b44d9f65..d38bd347 100644
--- a/lib/modules/gi.js
+++ b/lib/modules/gi.js
@@ -13,7 +13,7 @@ export function generateModule(namespace, version) {
const source = `
import $$gi from 'gi';
- const $$ns = $$gi.require${version ? `('${namespace}', '${version}')` : `(${namespace})`};
+ const $$ns = $$gi.require${version ? `('${namespace}', '${version}')` : `('${namespace}')`};
export default $$ns;
`;
diff --git a/modules/core/_text.js b/modules/core/_text.js
new file mode 100644
index 00000000..60d081d3
--- /dev/null
+++ b/modules/core/_text.js
@@ -0,0 +1,13 @@
+const ByteArray = imports.byteArray;
+
+var TextDecoder = class TextDecoder {
+ decode(bytes) {
+ return ByteArray.toString(bytes);
+ }
+}
+
+var TextEncoder = class TextEncoder {
+ encode(string) {
+ return ByteArray.fromString(string);
+ }
+}
\ No newline at end of file
diff --git a/modules/esm/cairo.js b/modules/esm/cairo.js
new file mode 100644
index 00000000..642f2ccc
--- /dev/null
+++ b/modules/esm/cairo.js
@@ -0,0 +1,7 @@
+const cairo = import.meta.importSync('cairoNative');
+
+export default Object.assign(
+ {},
+ imports._cairo,
+ cairo
+);
\ No newline at end of file
diff --git a/modules/esm/format.js b/modules/esm/format.js
index 8f4c47eb..1d5dc4c9 100644
--- a/modules/esm/format.js
+++ b/modules/esm/format.js
@@ -1,2 +1,5 @@
-export const format = imports._format.format;
-export const vprintf = imports._format.vprintf;
\ No newline at end of file
+export const vprintf = imports._format.vprintf;
+
+export function format(...args) {
+ return vprintf(this, args);
+}
\ No newline at end of file
diff --git a/modules/esm/gi.js b/modules/esm/gi.js
index f9cbc374..8ee1ef14 100644
--- a/modules/esm/gi.js
+++ b/modules/esm/gi.js
@@ -1,5 +1,7 @@
const gi = import.meta.importSync('gi');
+import System from 'system';
+
const Gi = {
require(name, version = null) {
if (version !== null)
@@ -11,6 +13,70 @@ const Gi = {
return gi[name];
},
+ requireSymbol(lib, ver, symbol) {
+ if (!checkSymbol(lib, ver, symbol)) {
+ if (symbol)
+ printerr(`Unsatisfied dependency: No ${symbol} in ${lib}`);
+ else
+ printerr(`Unsatisfied dependency: ${lib}`);
+ System.exit(1);
+ }
+ },
+
+ /**
+ * Check whether an external GI typelib can be imported
+ * and provides @symbol.
+ *
+ * Symbols may refer to
+ * - global functions ('main_quit')
+ * - classes ('Window')
+ * - class / instance methods ('IconTheme.get_default' / 'IconTheme.has_icon')
+ * - GObject properties ('Window.default_height')
+ *
+ * @param {string} lib an external dependency to import
+ * @param {string} [ver] version of the dependency
+ * @param {string} [symbol] symbol to check for
+ * @returns {boolean} true if `lib` can be imported and provides `symbol`, false
+ * otherwise
+ */
+ checkSymbol(lib, ver, symbol) {
+ let Lib = null;
+
+ if (ver)
+ gi.versions[lib] = ver;
+
+ try {
+ Lib = gi[lib];
+ } catch (e) {
+ return false;
+ }
+
+ if (!symbol)
+ return true; // Done
+
+ let [klass, sym] = symbol.split('.');
+ if (klass === symbol) // global symbol
+ return typeof Lib[symbol] !== 'undefined';
+
+ let obj = Lib[klass];
+ if (typeof obj === 'undefined')
+ return false;
+
+ if (typeof obj[sym] !== 'undefined' ||
+ obj.prototype && typeof obj.prototype[sym] !== 'undefined')
+ return true; // class- or object method
+
+ // GObject property
+ let pspec = null;
+ if (GObject.type_is_a(obj.$gtype, GObject.TYPE_INTERFACE)) {
+ let iface = GObject.type_default_interface_ref(obj.$gtype);
+ pspec = GObject.Object.interface_find_property(iface, sym);
+ } else if (GObject.type_is_a(obj.$gtype, GObject.TYPE_OBJECT)) {
+ pspec = GObject.Object.find_property.call(obj.$gtype, sym);
+ }
+
+ return pspec !== null;
+ }
};
Object.freeze(Gi);
diff --git a/modules/esm/signals.js b/modules/esm/signals.js
index 16946132..d997eda7 100644
--- a/modules/esm/signals.js
+++ b/modules/esm/signals.js
@@ -1,11 +1,3 @@
-const _signals = imports._signals;
-
-function _addSignalMethod(proto, functionName, func) {
- if (proto[functionName] && proto[functionName] !== func)
- log(`WARNING: addSignalMethods is replacing existing ${proto} ${functionName} method`);
-
- proto[functionName] = func;
-}
export class EventEmitter {
constructor() {
@@ -30,10 +22,6 @@ export class EventEmitter {
// we instantiate the "signal machinery" only on-demand if anything
// gets connected.
- if (!('_events' in this)) {
- this._events = [];
- this._nextConnectionId = 1n;
- }
let id = this._nextConnectionId;
this._nextConnectionId += 1n;
@@ -41,58 +29,52 @@ export class EventEmitter {
// this makes it O(n) in total connections to emit, but I think
// it's right to optimize for low memory and reentrancy-safety
// rather than speed
- this._events.push({
+
+ this._connectListener(name, {
id,
name,
callback,
'disconnected': false,
});
- this._connectListener(name, callback);
-
return id;
}
disconnect(id) {
- if ('_events' in this) {
- let i;
- let length = this._events.length;
- for (i = 0; i < length; ++i) {
- let connection = this._events[i];
+ this._events.forEach(_events => {
+ for (let i = 0; i < _events.length; ++i) {
+ let connection = _events[i];
if (connection.id === id) {
if (connection.disconnected)
throw new Error(`Signal handler id ${id} already disconnected`);
// set a flag to deal with removal during emission
connection.disconnected = true;
- this._events.splice(i, 1);
+ _events.splice(i, 1);
return;
}
}
- }
- throw new Error(`No signal connection ${id} found`);
+ });
}
signalHandlerIsConnected(id) {
- if (!('_events' in this))
- return false;
-
- const { length } = this._events;
- for (let i = 0; i < length; ++i) {
- const connection = this._events[i];
- if (connection.id === id)
- return !connection.disconnected;
- }
+ this._events.forEach(_events => {
+ for (let i = 0; i < _events.length; ++i) {
+ const connection = this._events[i];
+ if (connection.id === id)
+ return !connection.disconnected;
+ }
+ });
return false;
}
disconnectAll() {
- if ('_events' in this) {
- while (this._events.length > 0)
- _disconnect.call(this, this._events[0].id);
- }
+ this._events.forEach(_events => {
+ while (_events.length > 0)
+ this.disconnect.call(this, _events[0].id);
+ });
}
emit(name, ...args) {
@@ -104,14 +86,7 @@ export class EventEmitter {
// emitting), we copy out a list of what was connected
// at emission start; and just before invoking each
// handler we check its disconnected flag.
- let handlers = [];
- let i;
- let length = this._events.length;
- for (i = 0; i < length; ++i) {
- let connection = this._events[i];
- if (connection.name === name)
- handlers.push(connection);
- }
+ let handlers = [...(this._events.get(name) || [])];
// create arg array which is emitter + everything passed in except
// signal name. Would be more convenient not to pass emitter to
@@ -121,8 +96,7 @@ export class EventEmitter {
// which would be a cycle.
let argArray = [this, ...args];
- length = handlers.length;
- for (i = 0; i < length; ++i) {
+ for (let i = 0; i < handlers.length; ++i) {
let connection = handlers[i];
if (!connection.disconnected) {
try {
@@ -142,12 +116,3 @@ export class EventEmitter {
}
}
}
-
-export function addSignalMethods(proto) {
- _addSignalMethod(proto, 'connect', _connect);
- _addSignalMethod(proto, 'disconnect', _disconnect);
- _addSignalMethod(proto, 'emit', _emit);
- _addSignalMethod(proto, 'signalHandlerIsConnected', _signalHandlerIsConnected);
- // this one is not in GObject, but useful
- _addSignalMethod(proto, 'disconnectAll', _disconnectAll);
-}
diff --git a/modules/script/_bootstrap/default.js b/modules/script/_bootstrap/default.js
index eb042d49..e0c1090c 100644
--- a/modules/script/_bootstrap/default.js
+++ b/modules/script/_bootstrap/default.js
@@ -4,8 +4,21 @@
'use strict';
const {print, printerr, log, logError} = imports._print;
+ const {TextDecoder, TextEncoder} = imports._text;
Object.defineProperties(exports, {
+ TextDecoder: {
+ configurable: false,
+ enumerable: true,
+ writable: false,
+ value: TextDecoder,
+ },
+ TextEncoder: {
+ configurable: false,
+ enumerable: true,
+ writable: false,
+ value: TextEncoder,
+ },
print: {
configurable: false,
enumerable: true,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]