[gjs/esm/static-imports] WIP - implement parseURI in C++



commit 0dffdbf5534578e632ba68b55882a43d8480dd4f
Author: Philip Chimento <philip chimento gmail com>
Date:   Fri Dec 11 18:10:58 2020 -0800

    WIP - implement parseURI in C++
    
    Question: Does the function have to throw ImportError? see e.g.
    ModuleLoader.resolveRelativePath()

 gjs/global.cpp          |  1 +
 gjs/internal.cpp        | 82 +++++++++++++++++++++++++++++++++++++++++++++++++
 gjs/internal.h          |  5 +++
 lib/.eslintrc.yml       |  2 +-
 lib/bootstrap/module.js | 28 -----------------
 lib/modules/esm.js      |  4 ++-
 6 files changed, 92 insertions(+), 30 deletions(-)
---
diff --git a/gjs/global.cpp b/gjs/global.cpp
index 699a7de5..9e2e1b5a 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -272,6 +272,7 @@ class GjsInternalGlobal : GjsBaseGlobal {
               0),
         JS_FN("getRegistry", gjs_internal_global_get_registry, 1, 0),
         JS_FN("importSync", gjs_internal_global_import_sync, 1, 0),
+        JS_FN("parseURI", gjs_internal_parse_uri, 1, 0),
         JS_FN("setModuleLoadHook", gjs_internal_global_set_module_hook, 3, 0),
         JS_FN("setModuleMetaHook", gjs_internal_global_set_module_meta_hook, 2,
               0),
diff --git a/gjs/internal.cpp b/gjs/internal.cpp
index 72ea2120..a62d5bfb 100644
--- a/gjs/internal.cpp
+++ b/gjs/internal.cpp
@@ -391,3 +391,85 @@ bool gjs_internal_global_get_registry(JSContext* cx, unsigned argc,
     args.rval().setObject(*registry);
     return true;
 }
+
+bool gjs_internal_parse_uri(JSContext* cx, unsigned argc, JS::Value* vp) {
+    using AutoHashTable =
+        GjsAutoPointer<GHashTable, GHashTable, g_hash_table_destroy>;
+    using AutoURI = GjsAutoPointer<GUri, GUri, g_uri_unref>;
+
+    JS::CallArgs args = CallArgsFromVp(argc, vp);
+
+    g_assert(args.length() == 1 && "parseUri() takes one string argument");
+    g_assert(args[0].isString() && "parseUri() takes one string argument");
+
+    JS::RootedString string_arg(cx, args[0].toString());
+    JS::UniqueChars uri = JS_EncodeStringToUTF8(cx, string_arg);
+    if (!uri)
+        return false;
+
+    GError* error = nullptr;
+    AutoURI parsed = g_uri_parse(uri.get(), G_URI_FLAGS_NONE, &error);
+    if (!parsed)
+        return gjs_throw_gerror_message(cx, error);
+
+    JS::RootedObject query_obj(cx, JS_NewPlainObject(cx));
+    if (!query_obj)
+        return false;
+
+    const char* raw_query = g_uri_get_query(parsed);
+    if (raw_query) {
+        AutoHashTable query =
+            g_uri_parse_params(raw_query, -1, "&", G_URI_PARAMS_NONE, &error);
+        if (!query)
+            return gjs_throw_gerror_message(cx, error);
+
+        GHashTableIter iter;
+        g_hash_table_iter_init(&iter, query);
+
+        void* key_ptr;
+        void* value_ptr;
+        while (g_hash_table_iter_next(&iter, &key_ptr, &value_ptr)) {
+            auto* key = static_cast<const char*>(key_ptr);
+            auto* value = static_cast<const char*>(value_ptr);
+
+            JS::ConstUTF8CharsZ value_chars{value, strlen(value)};
+            JS::RootedString value_str(cx,
+                                       JS_NewStringCopyUTF8Z(cx, value_chars));
+            if (!value_str || !JS_DefineProperty(cx, query_obj, key, value_str,
+                                                 JSPROP_ENUMERATE))
+                return false;
+        }
+    }
+
+    JS::RootedObject return_obj(cx, JS_NewPlainObject(cx));
+    if (!return_obj)
+        return false;
+
+    // JS_NewStringCopyZ() used here and below because the URI components are
+    // %-encoded, meaning ASCII-only
+    JS::RootedString scheme(cx,
+                            JS_NewStringCopyZ(cx, g_uri_get_scheme(parsed)));
+    if (!scheme)
+        return false;
+
+    JS::RootedString host(cx, JS_NewStringCopyZ(cx, g_uri_get_host(parsed)));
+    if (!host)
+        return false;
+
+    JS::RootedString path(cx, JS_NewStringCopyZ(cx, g_uri_get_path(parsed)));
+    if (!path)
+        return false;
+
+    if (!JS_DefineProperty(cx, return_obj, "uri", string_arg,
+                           JSPROP_ENUMERATE) ||
+        !JS_DefineProperty(cx, return_obj, "scheme", scheme,
+                           JSPROP_ENUMERATE) ||
+        !JS_DefineProperty(cx, return_obj, "host", host, JSPROP_ENUMERATE) ||
+        !JS_DefineProperty(cx, return_obj, "path", path, JSPROP_ENUMERATE) ||
+        !JS_DefineProperty(cx, return_obj, "query", query_obj,
+                           JSPROP_ENUMERATE))
+        return false;
+
+    args.rval().setObject(*return_obj);
+    return true;
+}
diff --git a/gjs/internal.h b/gjs/internal.h
index bf550c8d..e6d1a4a3 100644
--- a/gjs/internal.h
+++ b/gjs/internal.h
@@ -9,6 +9,8 @@
 #include <js/TypeDecls.h>
 #include <jsapi.h>
 
+#include "gjs/macros.h"
+
 bool gjs_load_internal_module(JSContext* cx, const char* identifier);
 
 bool gjs_internal_compile_module(JSContext* cx, unsigned argc, JS::Value* vp);
@@ -34,4 +36,7 @@ bool gjs_internal_set_module_private(JSContext* cx, unsigned argc,
 bool gjs_internal_global_set_module_resolve_hook(JSContext* cx, unsigned argc,
                                                  JS::Value* vp);
 
+GJS_JSAPI_RETURN_CONVENTION
+bool gjs_internal_parse_uri(JSContext* cx, unsigned argc, JS::Value* vp);
+
 #endif  // GJS_INTERNAL_H_
diff --git a/lib/.eslintrc.yml b/lib/.eslintrc.yml
index fb5dfe5e..53cfdf5c 100644
--- a/lib/.eslintrc.yml
+++ b/lib/.eslintrc.yml
@@ -15,12 +15,12 @@ globals:
   logError: off
   print: off
   printerr: off
-  GLib: readonly
   Gio: readonly
   ByteUtils: readonly
   moduleGlobalThis: readonly
   compileModule: readonly
   compileInternalModule: readonly
+  parseURI: readonly
   setModuleResolveHook: readonly
   setModuleMetaHook: readonly
   setModuleLoadHook: readonly
diff --git a/lib/bootstrap/module.js b/lib/bootstrap/module.js
index 7323be1c..6b5c5f09 100644
--- a/lib/bootstrap/module.js
+++ b/lib/bootstrap/module.js
@@ -1,8 +1,6 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2020 Evan Welsh <contact evanwelsh com>
 
-// NOTE: Gio, GLib, and GObject have no overrides.
-
 /** @typedef {{ uri: string; scheme: string; host: string; path: string; query: Query }} Uri */
 
 /** @typedef {{ load(uri: Uri): [string, boolean]; }} SchemeHandler */
@@ -106,32 +104,6 @@ function resolveRelativeResourceOrFile(uri, relativePath) {
     throw new ImportError('File does not have a valid parent!');
 }
 
-/**
- * Parses a string into a Uri object
- *
- * @param {string} uri the URI to parse as a string
- * @returns {Uri}
- */
-export function parseURI(uri) {
-    try {
-        const parsed = GLib.Uri.parse(uri, GLib.UriFlags.NONE);
-
-        const raw_query = parsed.get_query();
-        const query = raw_query ? GLib.Uri.parse_params(raw_query, -1, '&', GLib.UriParamsFlags.NONE) : {};
-
-        return {
-            uri,
-            scheme: parsed.get_scheme(),
-            host: parsed.get_host(),
-            path: parsed.get_path(),
-            query,
-
-        };
-    } catch (error) {
-        throw new ImportError(`Attempted to import invalid URI: ${uri}`);
-    }
-}
-
 /**
  * Handles resolving and loading URIs.
  *
diff --git a/lib/modules/esm.js b/lib/modules/esm.js
index 27fc48ec..443ff273 100644
--- a/lib/modules/esm.js
+++ b/lib/modules/esm.js
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2020 Evan Welsh <contact evanwelsh com>
 
-import {ESModule, ImportError, loadResourceOrFile, ModuleLoader, parseURI} from '../bootstrap/module.js';
+/* global debug, finishDynamicModuleImport, initAndEval, setModuleDynamicImportHook, parseURI */
+
+import {ESModule, ImportError, loadResourceOrFile, ModuleLoader} from '../bootstrap/module.js';
 
 import {generateModule} from './gi.js';
 


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