[gjs: 1/5] GObject: Optionally use the caller script basename to define the GType



commit 02568304aff1268f0a9bc032d09b517fecd28803
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Sun Sep 1 08:22:38 2019 +0200

    GObject: Optionally use the caller script basename to define the GType
    
    When computing a GType we're only using the class name, but this
    might lead to clashes when the same name is used various times
    in a project.
    
    To reduce this possibility, add a GObject property
    (GObject.gtypeNameBasedOnJSPath) that can be set to true to make gjs
    try to compute the caller script path, by getting the first call
    coming from another script in the error stack (unfortunately it seems
    the only way in JS :().
    
    Then use this value to generate the GType name.

 modules/overrides/GObject.js | 50 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)
---
diff --git a/modules/overrides/GObject.js b/modules/overrides/GObject.js
index aa63a0f6..cccbf228 100644
--- a/modules/overrides/GObject.js
+++ b/modules/overrides/GObject.js
@@ -112,10 +112,56 @@ function _createSignals(gtype, sigs) {
     }
 }
 
+function _getCallerBasename() {
+    const stackLines = new Error().stack.trim().split('\n');
+    const lineRegex = new RegExp(/@(.+:\/\/)?(.*\/)?(.+)\.js:\d+(:[\d]+)?$/);
+    let thisFile = null;
+    let thisDir = null;
+
+    for (let line of stackLines) {
+        let match = line.match(lineRegex);
+        if (match) {
+            let scriptDir = match[2];
+            let scriptBasename = match[3];
+
+            if (!thisFile) {
+                thisDir = scriptDir;
+                thisFile = scriptBasename;
+                continue;
+            }
+
+            if (scriptDir === thisDir && scriptBasename === thisFile)
+                continue;
+
+            if (scriptDir && scriptDir.startsWith('/org/gnome/gjs/'))
+                continue;
+
+            let basename = scriptBasename;
+            if (scriptDir) {
+                scriptDir = scriptDir.replace(/^\/|\/$/g, '');
+                basename = `${scriptDir.split('/').reverse()[0]}_${basename}`;
+            }
+            return basename;
+        }
+    }
+
+    return null;
+}
+
 function _createGTypeName(klass) {
+    const sanitizeGType = s => s.replace(/[^a-z0-9+_-]/gi, '_');
+
     if (klass.hasOwnProperty(GTypeName))
         return klass[GTypeName];
-    return `Gjs_${klass.name.replace(/[^a-z0-9+_-]/gi, '_')}`;
+
+    let gtypeClassName = klass.name;
+    if (GObject.gtypeNameBasedOnJSPath) {
+        let callerBasename = _getCallerBasename();
+        if (callerBasename)
+            gtypeClassName = `${callerBasename}_${gtypeClassName}`;
+    }
+
+    return sanitizeGType(`Gjs_${gtypeClassName}`);
 }
 
 function _propertiesAsArray(klass) {
@@ -187,6 +233,8 @@ function _init() {
         obj[name].$gtype = gtype;
     }
 
+    GObject.gtypeNameBasedOnJSPath = false;
+
     _makeDummyClass(GObject, 'VoidType', 'NONE', 'void', function () {});
     _makeDummyClass(GObject, 'Char', 'CHAR', 'gchar', Number);
     _makeDummyClass(GObject, 'UChar', 'UCHAR', 'guchar', Number);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]