[gjs: 3/10] context: Move atoms to a separate class



commit 8e707747d676dda92051f98115b17b0afe0aeeb9
Author: Philip Chimento <philip chimento gmail com>
Date:   Sat Nov 3 15:46:02 2018 -0400

    context: Move atoms to a separate class
    
    This moves the atoms (interned strings) from GjsContextPrivate to a
    separate class, so that we can decouple them from GjsContext, since in
    some cases we will want to use them only with the SpiderMonkey API.

 gi/arg.cpp                  | 19 ++++-----
 gi/boxed.cpp                | 13 +++---
 gi/fundamental.cpp          |  7 ++--
 gi/gerror.cpp               | 39 +++++++++---------
 gi/gobject.cpp              |  3 +-
 gi/interface.cpp            |  5 ++-
 gi/object.cpp               |  6 ++-
 gi/param.cpp                |  4 +-
 gi/repo.cpp                 | 42 ++++++++++----------
 gi/value.cpp                | 11 +++---
 gjs-srcs.mk                 |  2 +
 gjs/atoms.cpp               | 43 ++++++++++++++++++++
 gjs/atoms.h                 | 80 +++++++++++++++++++++++++++++++++++++
 gjs/context-private.h       | 13 +++---
 gjs/context.cpp             | 37 ++---------------
 gjs/global.cpp              |  6 ++-
 gjs/importer.cpp            | 36 ++++++++---------
 gjs/jsapi-dynamic-class.cpp | 17 ++++----
 gjs/jsapi-util-error.cpp    |  7 ++--
 gjs/jsapi-util.cpp          | 96 ++++-----------------------------------------
 gjs/jsapi-util.h            | 96 ---------------------------------------------
 modules/cairo-region.cpp    | 10 +++--
 22 files changed, 262 insertions(+), 330 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index a4e96e94..8ab18290 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -1317,18 +1317,19 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
             goto out;
     } else {
         JS::RootedObject array_obj(context, &value.toObject());
+        const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
         GITypeTag element_type = g_type_info_get_tag(param_info);
         if (JS_IsUint8Array(array_obj) && (element_type == GI_TYPE_TAG_INT8 ||
                                            element_type == GI_TYPE_TAG_UINT8)) {
             GBytes* bytes = gjs_byte_array_get_bytes(array_obj);
             *contents = g_bytes_unref_to_data(bytes, length_p);
-        } else if (gjs_object_has_property(context, array_obj,
-                                           GJS_STRING_LENGTH, &found_length) &&
+        } else if (JS_HasPropertyById(context, array_obj, atoms.length(),
+                                      &found_length) &&
                    found_length) {
             guint32 length;
 
-            if (!gjs_object_require_converted_property(context, array_obj, NULL,
-                                                       GJS_STRING_LENGTH, &length)) {
+            if (!gjs_object_require_converted_property(
+                    context, array_obj, nullptr, atoms.length(), &length)) {
                 goto out;
             } else {
                 if (!gjs_array_to_array(context,
@@ -1889,16 +1890,16 @@ gjs_value_to_g_argument(JSContext      *context,
          */
         if (value.isObject()) {
             bool found_length;
+            const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
             JS::RootedObject array_obj(context, &value.toObject());
 
-            if (gjs_object_has_property(context, array_obj,
-                                        GJS_STRING_LENGTH, &found_length) &&
+            if (JS_HasPropertyById(context, array_obj, atoms.length(),
+                                   &found_length) &&
                 found_length) {
                 guint32 length;
 
-                if (!gjs_object_require_converted_property(context, array_obj,
-                                                           NULL, GJS_STRING_LENGTH,
-                                                           &length)) {
+                if (!gjs_object_require_converted_property(
+                        context, array_obj, nullptr, atoms.length(), &length)) {
                     wrong = true;
                 } else {
                     GList *list;
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index ec43cb3b..9d6592a9 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -319,8 +319,8 @@ boxed_invoke_constructor(JSContext             *context,
 {
     JS::RootedObject js_constructor(context);
 
-    if (!gjs_object_require_property(context, obj, NULL,
-                                     GJS_STRING_CONSTRUCTOR,
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+    if (!gjs_object_require_property(context, obj, NULL, atoms.constructor(),
                                      &js_constructor))
         return false;
 
@@ -343,9 +343,9 @@ boxed_new(JSContext             *context,
     if (priv->gtype == G_TYPE_VARIANT) {
         /* Short-circuit construction for GVariants by calling into the JS packing
            function */
-        JS::HandleId constructor_name =
-            gjs_context_get_const_string(context, GJS_STRING_NEW_INTERNAL);
-        return boxed_invoke_constructor(context, obj, constructor_name, args);
+        const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+        return boxed_invoke_constructor(context, obj, atoms.new_internal(),
+                                        args);
     }
 
     /* If the structure is registered as a boxed, we can create a new instance by
@@ -1102,7 +1102,8 @@ boxed_fill_prototype_info(JSContext *context,
                 if (priv->default_constructor < 0 &&
                     strcmp(g_base_info_get_name ((GIBaseInfo*) func_info), "new") == 0) {
                     priv->default_constructor = i;
-                    priv->default_constructor_name = gjs_context_get_const_string(context, GJS_STRING_NEW);
+                    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+                    priv->default_constructor_name = atoms.new_();
                 }
             }
 
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 85400ea1..b04e38b7 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -376,8 +376,8 @@ fundamental_invoke_constructor(FundamentalInstance        *priv,
 {
     JS::RootedObject js_constructor(context);
 
-    if (!gjs_object_require_property(context, obj, NULL,
-                                     GJS_STRING_CONSTRUCTOR,
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+    if (!gjs_object_require_property(context, obj, NULL, atoms.constructor(),
                                      &js_constructor) ||
         priv->prototype->constructor_name.get() == JSID_VOID) {
         gjs_throw (context,
@@ -603,9 +603,10 @@ gjs_lookup_fundamental_prototype(JSContext    *context,
 
     g_assert(constructor);
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     JS::RootedObject prototype(context);
     if (!gjs_object_require_property(context, constructor, "constructor object",
-                                     GJS_STRING_PROTOTYPE, &prototype))
+                                     atoms.prototype(), &prototype))
         return NULL;
 
     return prototype;
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index e87af80a..7cee0ec8 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -27,11 +27,12 @@
 
 #include "boxed.h"
 #include "enumeration.h"
+#include "gerror.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-wrapper.h"
 #include "gjs/mem.h"
 #include "repo.h"
-#include "gerror.h"
 #include "util/error.h"
 
 #include <util/log.h>
@@ -96,14 +97,13 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(error)
 
     JS::RootedObject params_obj(context, &argv[0].toObject());
     JS::UniqueChars message;
-    if (!gjs_object_require_property(context, params_obj,
-                                     "GError constructor",
-                                     GJS_STRING_MESSAGE, &message))
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+    if (!gjs_object_require_property(context, params_obj, "GError constructor",
+                                     atoms.message(), &message))
         return false;
 
-    if (!gjs_object_require_property(context, params_obj,
-                                     "GError constructor",
-                                     GJS_STRING_CODE, &code))
+    if (!gjs_object_require_property(context, params_obj, "GError constructor",
+                                     atoms.code(), &code))
         return false;
 
     priv->gerror = g_error_new_literal(priv->domain, code, message.get());
@@ -245,9 +245,10 @@ error_constructor_value_of(JSContext *context,
     GJS_GET_THIS(context, argc, vp, rec, self);
     Error *priv;
     JS::RootedObject prototype(context);
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
 
     if (!gjs_object_require_property(context, self, "constructor",
-                                     GJS_STRING_PROTOTYPE, &prototype)) {
+                                     atoms.prototype(), &prototype)) {
         /* This error message will be more informative */
         JS_ClearPendingException(context);
         gjs_throw(context, "GLib.Error.valueOf() called on something that is not"
@@ -398,14 +399,15 @@ bool gjs_define_error_properties(JSContext* cx, JS::HandleObject obj) {
         return false;
     }
 
-    return gjs_object_define_property(cx, obj, GJS_STRING_STACK, stack,
-                                      JSPROP_ENUMERATE) &&
-           gjs_object_define_property(cx, obj, GJS_STRING_FILENAME, source,
-                                      JSPROP_ENUMERATE) &&
-           gjs_object_define_property(cx, obj, GJS_STRING_LINE_NUMBER, line,
-                                      JSPROP_ENUMERATE) &&
-           gjs_object_define_property(cx, obj, GJS_STRING_COLUMN_NUMBER, column,
-                                      JSPROP_ENUMERATE);
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
+    return JS_DefinePropertyById(cx, obj, atoms.stack(), stack,
+                                 JSPROP_ENUMERATE) &&
+           JS_DefinePropertyById(cx, obj, atoms.file_name(), source,
+                                 JSPROP_ENUMERATE) &&
+           JS_DefinePropertyById(cx, obj, atoms.line_number(), line,
+                                 JSPROP_ENUMERATE) &&
+           JS_DefinePropertyById(cx, obj, atoms.column_number(), column,
+                                 JSPROP_ENUMERATE);
 }
 
 GJS_USE
@@ -558,8 +560,9 @@ gjs_gerror_make_from_error(JSContext       *cx,
 
     /* Try to make something useful from the error
        name and message (in case this is a JS error) */
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
     JS::RootedValue v_name(cx);
-    if (!gjs_object_get_property(cx, obj, GJS_STRING_NAME, &v_name))
+    if (!JS_GetPropertyById(cx, obj, atoms.name(), &v_name))
         return nullptr;
 
     JS::UniqueChars name;
@@ -567,7 +570,7 @@ gjs_gerror_make_from_error(JSContext       *cx,
         return nullptr;
 
     JS::RootedValue v_message(cx);
-    if (!gjs_object_get_property(cx, obj, GJS_STRING_MESSAGE, &v_message))
+    if (!JS_GetPropertyById(cx, obj, atoms.message(), &v_message))
         return nullptr;
 
     JS::UniqueChars message;
diff --git a/gi/gobject.cpp b/gi/gobject.cpp
index d088a722..1be87fc9 100644
--- a/gi/gobject.cpp
+++ b/gi/gobject.cpp
@@ -207,8 +207,9 @@ static void gjs_object_custom_init(GTypeInstance* instance, void* klass) {
      * just do this from the start */
     priv->ensure_uses_toggle_ref(cx);
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
     JS::RootedValue v(cx);
-    if (!gjs_object_get_property(cx, object, GJS_STRING_INSTANCE_INIT, &v)) {
+    if (!JS_GetPropertyById(cx, object, atoms.instance_init(), &v)) {
         gjs_log_exception(cx);
         return;
     }
diff --git a/gi/interface.cpp b/gi/interface.cpp
index c4000aa3..f5c8e363 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -164,9 +164,10 @@ interface_has_instance_func(JSContext *cx,
     g_assert(interface.isObject());
     JS::RootedObject interface_constructor(cx, &interface.toObject());
     JS::RootedObject interface_proto(cx);
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
     if (!gjs_object_require_property(cx, interface_constructor,
-                                     "interface constructor",
-                                     GJS_STRING_PROTOTYPE, &interface_proto))
+                                     "interface constructor", atoms.prototype(),
+                                     &interface_proto))
         return false;
 
     Interface *priv;
diff --git a/gi/object.cpp b/gi/object.cpp
index 36201166..ab39a329 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1661,8 +1661,9 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(object_instance)
      * might be traced and we will end up dereferencing a null pointer */
     JS_SetPrivate(object, ObjectInstance::new_for_js_object(context, object));
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     if (!gjs_object_require_property(context, object, "GObject instance",
-                                     GJS_STRING_GOBJECT_INIT, &initer))
+                                     atoms.init(), &initer))
         return false;
 
     argv.rval().setUndefined();
@@ -1822,9 +1823,10 @@ gjs_lookup_object_prototype_from_info(JSContext    *context,
     if (G_UNLIKELY(!constructor))
         return NULL;
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     JS::RootedObject prototype(context);
     if (!gjs_object_require_property(context, constructor, "constructor object",
-                                     GJS_STRING_PROTOTYPE, &prototype))
+                                     atoms.prototype(), &prototype))
         return NULL;
 
     return prototype;
diff --git a/gi/param.cpp b/gi/param.cpp
index 265e51f2..3a68ad40 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -180,8 +180,8 @@ gjs_lookup_param_prototype(JSContext    *context)
     JS::RootedObject constructor(context, &value.toObject());
     g_assert(constructor);
 
-    if (!gjs_object_get_property(context, constructor,
-                                 GJS_STRING_PROTOTYPE, &value))
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+    if (!JS_GetPropertyById(context, constructor, atoms.prototype(), &value))
         return NULL;
 
     if (G_UNLIKELY (!value.isObjectOrNull()))
diff --git a/gi/repo.cpp b/gi/repo.cpp
index f5f65dec..404806ec 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -63,10 +63,10 @@ static bool get_version_for_ns(JSContext* context, JS::HandleObject repo_obj,
                                JS::HandleId ns_id, JS::UniqueChars* version) {
     JS::RootedObject versions(context);
     bool found;
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
 
-    if (!gjs_object_require_property(context, repo_obj,
-                                     "GI repository object",
-                                     GJS_STRING_GI_VERSIONS, &versions))
+    if (!gjs_object_require_property(context, repo_obj, "GI repository object",
+                                     atoms.versions(), &versions))
         return false;
 
     if (!JS_AlreadyHasOwnPropertyById(context, versions, ns_id, &found))
@@ -269,9 +269,11 @@ repo_new(JSContext *context)
     gjs_debug_lifecycle(GJS_DEBUG_GREPO,
                         "repo constructor, obj %p priv %p", repo.get(), priv);
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     JS::RootedObject versions(context, JS_NewPlainObject(context));
-    gjs_object_define_property(context, repo, GJS_STRING_GI_VERSIONS,
-                               versions, JSPROP_PERMANENT | JSPROP_RESOLVING);
+    if (!JS_DefinePropertyById(context, repo, atoms.versions(), versions,
+                               JSPROP_PERMANENT | JSPROP_RESOLVING))
+        return nullptr;
 
     /* GLib/GObject/Gio are fixed at 2.0, since we depend on them
      * internally.
@@ -288,9 +290,9 @@ repo_new(JSContext *context)
         return nullptr;
 
     JS::RootedObject private_ns(context, JS_NewPlainObject(context));
-    gjs_object_define_property(context, repo,
-                               GJS_STRING_PRIVATE_NS_MARKER, private_ns,
-                               JSPROP_PERMANENT | JSPROP_RESOLVING);
+    if (!JS_DefinePropertyById(context, repo, atoms.private_ns_marker(),
+                               private_ns, JSPROP_PERMANENT | JSPROP_RESOLVING))
+        return nullptr;
 
     return repo;
 }
@@ -523,9 +525,9 @@ gjs_define_info(JSContext       *context,
 JSObject*
 gjs_lookup_private_namespace(JSContext *context)
 {
-    JS::HandleId ns_name =
-        gjs_context_get_const_string(context, GJS_STRING_PRIVATE_NS_MARKER);
-    return gjs_lookup_namespace_object_by_name(context, ns_name);
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+    return gjs_lookup_namespace_object_by_name(context,
+                                               atoms.private_ns_marker());
 }
 
 /* Get the namespace object that the GIBaseInfo should be inside */
@@ -563,8 +565,9 @@ error_has_name(JSContext       *cx,
     JS::RootedObject exc(cx, &thrown_value.toObject());
     JS::RootedValue exc_name(cx);
     bool retval = false;
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
 
-    if (!gjs_object_get_property(cx, exc, GJS_STRING_NAME, &exc_name))
+    if (!JS_GetPropertyById(cx, exc, atoms.name(), &exc_name))
         goto out;
 
     int32_t cmp_result;
@@ -593,10 +596,9 @@ lookup_override_function(JSContext             *cx,
 
     JS::RootedObject overridespkg(cx), module(cx);
     JS::RootedObject importer_obj(cx, &importer.toObject());
-
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
     if (!gjs_object_require_property(cx, importer_obj, "importer",
-                                     GJS_STRING_GI_OVERRIDES,
-                                     &overridespkg))
+                                     atoms.overrides(), &overridespkg))
         goto fail;
 
     if (!gjs_object_require_property(cx, overridespkg,
@@ -616,7 +618,7 @@ lookup_override_function(JSContext             *cx,
     }
 
     if (!gjs_object_require_property(cx, module, "override module",
-                                     GJS_STRING_GOBJECT_INIT, function) ||
+                                     atoms.init(), function) ||
         !function.isObjectOrNull()) {
         gjs_throw(cx, "Unexpected value for _init in overrides module");
         goto fail;
@@ -639,9 +641,9 @@ gjs_lookup_namespace_object_by_name(JSContext      *context,
     g_assert(importer.isObject());
 
     JS::RootedObject repo(context), importer_obj(context, &importer.toObject());
-
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     if (!gjs_object_require_property(context, importer_obj, "importer",
-                                     GJS_STRING_GI_MODULE, &repo)) {
+                                     atoms.gi(), &repo)) {
         gjs_log_exception(context);
         gjs_throw(context, "No gi property in importer");
         return NULL;
@@ -758,9 +760,9 @@ gjs_lookup_generic_prototype(JSContext  *context,
     if (G_UNLIKELY(!constructor))
         return NULL;
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     JS::RootedValue value(context);
-    if (!gjs_object_get_property(context, constructor,
-                                 GJS_STRING_PROTOTYPE, &value))
+    if (!JS_GetPropertyById(context, constructor, atoms.prototype(), &value))
         return NULL;
 
     if (G_UNLIKELY (!value.isObjectOrNull()))
diff --git a/gi/value.cpp b/gi/value.cpp
index a4827652..1ad596e3 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -478,16 +478,15 @@ gjs_value_to_g_value_internal(JSContext      *context,
         if (value.isNull()) {
             /* do nothing */
         } else {
+            const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
             JS::RootedObject array_obj(context, &value.toObject());
-            if (gjs_object_has_property(context, array_obj,
-                                        GJS_STRING_LENGTH, &found_length) &&
+            if (JS_HasPropertyById(context, array_obj, atoms.length(),
+                                   &found_length) &&
                 found_length) {
                 guint32 length;
 
-                if (!gjs_object_require_converted_property(context, array_obj,
-                                                           NULL,
-                                                           GJS_STRING_LENGTH,
-                                                           &length)) {
+                if (!gjs_object_require_converted_property(
+                        context, array_obj, nullptr, atoms.length(), &length)) {
                     JS_ClearPendingException(context);
                     return throw_expect_type(context, value, "strv");
                 } else {
diff --git a/gjs-srcs.mk b/gjs-srcs.mk
index aca65c60..47fdf949 100644
--- a/gjs-srcs.mk
+++ b/gjs-srcs.mk
@@ -54,6 +54,8 @@ gjs_srcs =                            \
        gi/union.h                      \
        gi/value.cpp                    \
        gi/value.h                      \
+       gjs/atoms.cpp                   \
+       gjs/atoms.h                     \
        gjs/byteArray.cpp               \
        gjs/byteArray.h                 \
        gjs/context.cpp                 \
diff --git a/gjs/atoms.cpp b/gjs/atoms.cpp
new file mode 100644
index 00000000..147bddef
--- /dev/null
+++ b/gjs/atoms.cpp
@@ -0,0 +1,43 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2018 Philip Chimento <philip chimento gmail com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "gjs/atoms.h"
+#include "gjs/jsapi-wrapper.h"
+
+GjsAtoms::GjsAtoms(JSContext* cx) {
+    JSAutoRequest ar(cx);
+    JSString* atom;
+
+#define INITIALIZE_ATOM(identifier, str)    \
+    atom = JS_AtomizeAndPinString(cx, str); \
+    m_##identifier = INTERNED_STRING_TO_JSID(cx, atom);
+    FOR_EACH_ATOM(INITIALIZE_ATOM)
+#undef INITIALIZE_ATOM
+}
+
+void GjsAtoms::trace(JSTracer* trc) {
+#define TRACE_ATOM(identifier, str) \
+    JS::TraceEdge<jsid>(trc, &m_##identifier, "Atom " str);
+    FOR_EACH_ATOM(TRACE_ATOM)
+#undef TRACE_ATOM
+}
diff --git a/gjs/atoms.h b/gjs/atoms.h
new file mode 100644
index 00000000..7028e9b8
--- /dev/null
+++ b/gjs/atoms.h
@@ -0,0 +1,80 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2018 Philip Chimento <philip chimento gmail com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef GJS_ATOMS_H_
+#define GJS_ATOMS_H_
+
+#include "gjs/jsapi-wrapper.h"
+
+// clang-format off
+#define FOR_EACH_ATOM(macro) \
+    macro(code, "code") \
+    macro(column_number, "columnNumber") \
+    macro(constructor, "constructor") \
+    macro(file_name, "fileName") \
+    macro(gi, "gi") \
+    macro(height, "height") \
+    macro(imports, "imports") \
+    macro(init, "_init") \
+    macro(instance_init, "_instance_init") \
+    macro(length, "length") \
+    macro(line_number, "lineNumber") \
+    macro(message, "message") \
+    macro(module_init, "__init__") \
+    macro(module_path, "__modulePath__") \
+    macro(name, "name") \
+    macro(new_, "new") \
+    macro(new_internal, "_new_internal") \
+    macro(overrides, "overrides") \
+    macro(parent_module, "__parentModule__") \
+    macro(private_ns_marker, "__gjsPrivateNS") \
+    macro(prototype, "prototype") \
+    macro(search_path, "searchPath") \
+    macro(stack, "stack") \
+    macro(versions, "versions") \
+    macro(width, "width") \
+    macro(x, "x") \
+    macro(y, "y")
+// clang-format on
+
+class GjsAtoms {
+#define DECLARE_ATOM_MEMBER(identifier, str) JS::Heap<jsid> m_##identifier;
+    FOR_EACH_ATOM(DECLARE_ATOM_MEMBER)
+#undef DECLARE_ATOM_MEMBER
+
+ public:
+    explicit GjsAtoms(JSContext* cx);
+
+    void trace(JSTracer* trc);
+
+/* It's OK to return JS::HandleId here, to avoid an extra root, with the caveat
+ * that you should not use this value after the GjsContext has been destroyed.*/
+#define DECLARE_ATOM_ACCESSOR(identifier, str)                          \
+    JS::HandleId identifier(void) const {                               \
+        return JS::HandleId::fromMarkedLocation(&m_##identifier.get()); \
+    }
+    FOR_EACH_ATOM(DECLARE_ATOM_ACCESSOR)
+#undef DECLARE_ATOM_ACCESSOR
+};
+
+#endif  // GJS_ATOMS_H_
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 07d402c1..a87c6811 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -29,6 +29,7 @@
 #include <unordered_map>
 
 #include "context.h"
+#include "gjs/atoms.h"
 #include "jsapi-util.h"
 #include "jsapi-wrapper.h"
 
@@ -46,7 +47,7 @@ class GjsContextPrivate {
 
     unsigned m_auto_gc_id;
 
-    std::array<JS::PersistentRootedId*, GJS_STRING_LAST> m_atoms;
+    GjsAtoms m_atoms;
 
     JS::PersistentRooted<JobQueue>* m_job_queue;
     unsigned m_idle_drain_handler;
@@ -107,6 +108,7 @@ class GjsContextPrivate {
     GJS_USE JSContext* context(void) const { return m_cx; }
     GJS_USE JSObject* global(void) const { return m_global.get(); }
     GJS_USE GjsProfiler* profiler(void) const { return m_profiler; }
+    GJS_USE const GjsAtoms& atoms(void) const { return m_atoms; }
     GJS_USE bool destroying(void) const { return m_destroying; }
     GJS_USE bool sweeping(void) const { return m_in_gc_sweep; }
     void set_sweeping(bool value) { m_in_gc_sweep = value; }
@@ -120,6 +122,8 @@ class GjsContextPrivate {
     GJS_USE bool is_owner_thread(void) const {
         return m_owner_thread == g_thread_self();
     }
+    GJS_USE
+    static const GjsAtoms& atoms(JSContext* cx) { return from_cx(cx)->m_atoms; }
 
     GJS_JSAPI_RETURN_CONVENTION
     bool eval(const char* script, ssize_t script_len, const char* filename,
@@ -140,13 +144,6 @@ class GjsContextPrivate {
 
     void free_profiler(void);
     void dispose(void);
-
-    /* It's OK to return JS::HandleId here, to avoid an extra root, with the
-     * caveat that you should not use this value after the GjsContext has
-     * been destroyed. */
-    GJS_USE static JS::HandleId atom(JSContext* cx, GjsConstString name) {
-        return *GjsContextPrivate::from_cx(cx)->m_atoms[name];
-    }
 };
 
 #endif  /* __GJS_CONTEXT_PRIVATE_H__ */
diff --git a/gjs/context.cpp b/gjs/context.cpp
index f306515b..8096cd3f 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -84,19 +84,6 @@ struct _GjsContext {
     GObject parent;
 };
 
-/* Keep this consistent with GjsConstString in context-private.h */
-static const char *const_strings[] = {
-    "constructor", "prototype", "length",
-    "imports", "__parentModule__", "__init__", "searchPath",
-    "__gjsPrivateNS",
-    "gi", "versions", "overrides",
-    "_init", "_instance_init", "_new_internal", "new",
-    "message", "code", "stack", "fileName", "lineNumber", "columnNumber",
-    "name", "x", "y", "width", "height", "__modulePath__"
-};
-
-G_STATIC_ASSERT(G_N_ELEMENTS(const_strings) == GJS_STRING_LAST);
-
 struct _GjsContextClass {
     GObjectClass parent;
 };
@@ -381,10 +368,6 @@ void GjsContextPrivate::dispose(void) {
         JS_RemoveExtraGCRootsTracer(m_cx, &GjsContextPrivate::trace, this);
         m_global = nullptr;
 
-        gjs_debug(GJS_DEBUG_CONTEXT, "Unrooting atoms");
-        for (auto& root : m_atoms)
-            delete root;
-
         gjs_debug(GJS_DEBUG_CONTEXT, "Freeing allocated resources");
         delete m_job_queue;
 
@@ -441,7 +424,10 @@ gjs_context_constructed(GObject *object)
 }
 
 GjsContextPrivate::GjsContextPrivate(JSContext* cx, GjsContext* public_context)
-    : m_public_context(public_context), m_cx(cx), m_environment_preparer(cx) {
+    : m_public_context(public_context),
+      m_cx(cx),
+      m_atoms(cx),
+      m_environment_preparer(cx) {
     m_owner_thread = g_thread_self();
 
     const char *env_profiler = g_getenv("GJS_ENABLE_PROFILER");
@@ -459,11 +445,6 @@ GjsContextPrivate::GjsContextPrivate(JSContext* cx, GjsContext* public_context)
         }
     }
 
-    for (size_t ix = 0; ix < GJS_STRING_LAST; ix++) {
-        m_atoms[ix] = new JS::PersistentRootedId(
-            m_cx, gjs_intern_string_to_id(m_cx, const_strings[ix]));
-    }
-
     m_job_queue = new JS::PersistentRooted<JobQueue>(m_cx);
     if (!m_job_queue)
         g_error("Failed to initialize promise job queue");
@@ -950,16 +931,6 @@ gjs_context_make_current (GjsContext *context)
     current_context = context;
 }
 
-/* It's OK to return JS::HandleId here, to avoid an extra root, with the
- * caveat that you should not use this value after the GjsContext has
- * been destroyed. */
-JS::HandleId
-gjs_context_get_const_string(JSContext      *context,
-                             GjsConstString  name)
-{
-    return GjsContextPrivate::atom(context, name);
-}
-
 /**
  * gjs_get_import_global:
  * @context: a #JSContext
diff --git a/gjs/global.cpp b/gjs/global.cpp
index 7bb8c0c6..8a1cd1d2 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -25,6 +25,7 @@
 
 #include <gio/gio.h>
 
+#include "gjs/context-private.h"
 #include "gjs/engine.h"
 #include "global.h"
 #include "importer.h"
@@ -271,11 +272,12 @@ class GjsGlobal {
                   v_importer.isObject()));
         JS::RootedObject root_importer(cx, &v_importer.toObject());
 
+        const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
         /* Wrapping is a no-op if the importer is already in the same
          * compartment. */
         if (!JS_WrapObject(cx, &root_importer) ||
-            !gjs_object_define_property(cx, global, GJS_STRING_IMPORTS,
-                                        root_importer, GJS_MODULE_PROP_FLAGS))
+            !JS_DefinePropertyById(cx, global, atoms.imports(), root_importer,
+                                   GJS_MODULE_PROP_FLAGS))
             return false;
 
         if (bootstrap_script) {
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 1a8f61fa..59b7c48a 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -27,6 +27,7 @@
 
 #include <vector>
 
+#include "gjs/context-private.h"
 #include "importer.h"
 #include "jsapi-class.h"
 #include "jsapi-wrapper.h"
@@ -73,9 +74,9 @@ importer_to_string(JSContext *cx,
     GJS_GET_THIS(cx, argc, vp, args, importer);
     const JSClass *klass = JS_GetClass(importer);
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
     JS::RootedValue module_path(cx);
-    if (!gjs_object_get_property(cx, importer, GJS_STRING_MODULE_PATH,
-                                 &module_path))
+    if (!JS_GetPropertyById(cx, importer, atoms.module_path(), &module_path))
         return false;
 
     GjsAutoChar output;
@@ -138,10 +139,10 @@ define_meta_properties(JSContext       *context,
             return false;
         parent_module_val.setObject(*parent);
 
+        const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
         JS::RootedValue parent_module_path(context);
-        if (!gjs_object_get_property(context, parent,
-                                     GJS_STRING_MODULE_PATH,
-                                     &parent_module_path))
+        if (!JS_GetPropertyById(context, parent, atoms.module_path(),
+                                &parent_module_path))
             return false;
 
         GjsAutoChar module_path_buf;
@@ -339,15 +340,15 @@ GJS_JSAPI_RETURN_CONVENTION
 static JSObject* load_module_init(JSContext* cx, JS::HandleObject in_object,
                                   const char* full_path) {
     bool found;
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
 
     /* First we check if js module has already been loaded  */
-    if (!gjs_object_has_property(cx, in_object, GJS_STRING_MODULE_INIT,
-                                 &found))
+    if (!JS_HasPropertyById(cx, in_object, atoms.module_init(), &found))
         return nullptr;
     if (found) {
         JS::RootedValue v_module(cx);
-        if (!gjs_object_get_property(cx, in_object, GJS_STRING_MODULE_INIT,
-                                     &v_module))
+        if (!JS_GetPropertyById(cx, in_object, atoms.module_init(),
+                                &v_module))
             return nullptr;
         if (v_module.isObject())
             return &v_module.toObject();
@@ -367,9 +368,8 @@ static JSObject* load_module_init(JSContext* cx, JS::HandleObject in_object,
         return module_obj;
     }
 
-    if (!gjs_object_define_property(cx, in_object,
-                                    GJS_STRING_MODULE_INIT, module_obj,
-                                    GJS_MODULE_PROP_FLAGS & ~JSPROP_PERMANENT))
+    if (!JS_DefinePropertyById(cx, in_object, atoms.module_init(), module_obj,
+                               GJS_MODULE_PROP_FLAGS & ~JSPROP_PERMANENT))
         return nullptr;
 
     return module_obj;
@@ -474,9 +474,10 @@ static bool do_import(JSContext* context, JS::HandleObject obj, Importer* priv,
     guint32 search_path_len;
     guint32 i;
     bool exists, is_array;
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
 
     if (!gjs_object_require_property(context, obj, "importer",
-                                     GJS_STRING_SEARCH_PATH, &search_path))
+                                     atoms.search_path(), &search_path))
         return false;
 
     if (!JS_IsArrayObject(context, search_path, &is_array))
@@ -629,6 +630,7 @@ static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
     guint32 search_path_len;
     guint32 i;
     bool is_array;
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
 
     priv = priv_from_js(context, object);
 
@@ -638,8 +640,7 @@ static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
 
     JS::RootedObject search_path(context);
     if (!gjs_object_require_property(context, object, "importer",
-                                     GJS_STRING_SEARCH_PATH,
-                                     &search_path))
+                                     atoms.search_path(), &search_path))
         return false;
 
     if (!JS_IsArrayObject(context, search_path, &is_array))
@@ -741,15 +742,14 @@ importer_resolve(JSContext        *context,
                  bool             *resolved)
 {
     Importer *priv;
-    jsid module_init_name;
 
     if (!JSID_IS_STRING(id)) {
         *resolved = false;
         return true;
     }
 
-    module_init_name = gjs_context_get_const_string(context, GJS_STRING_MODULE_INIT);
-    if (id == module_init_name) {
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+    if (id == atoms.module_init()) {
         *resolved = false;
         return true;
     }
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index 8cbe31b7..2e686cb6 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -28,6 +28,7 @@
 #include <util/glib.h>
 #include <util/misc.h>
 
+#include "gjs/context-private.h"
 #include "jsapi-class.h"
 #include "jsapi-util.h"
 #include "jsapi-wrapper.h"
@@ -125,13 +126,13 @@ gjs_init_class_dynamic(JSContext              *context,
     } else {
         /* Have to fake it with JSPROP_RESOLVING, otherwise it will trigger
          * the resolve hook */
-        if (!gjs_object_define_property(context, constructor,
-                                        GJS_STRING_PROTOTYPE, prototype,
-                                        JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
+        const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
+        if (!JS_DefinePropertyById(
+                context, constructor, atoms.prototype(), prototype,
+                JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
             goto out;
-        if (!gjs_object_define_property(context, prototype,
-                                        GJS_STRING_CONSTRUCTOR, constructor,
-                                        JSPROP_RESOLVING))
+        if (!JS_DefinePropertyById(context, prototype, atoms.constructor(),
+                                   constructor, JSPROP_RESOLVING))
             goto out;
     }
 
@@ -191,11 +192,11 @@ gjs_construct_object_dynamic(JSContext                  *context,
 {
     JSAutoRequest ar(context);
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     JS::RootedObject constructor(context);
 
     if (!gjs_object_require_property(context, proto, "prototype",
-                                     GJS_STRING_CONSTRUCTOR,
-                                     &constructor))
+                                     atoms.constructor(), &constructor))
         return NULL;
 
     return JS_New(context, constructor, args);
diff --git a/gjs/jsapi-util-error.cpp b/gjs/jsapi-util-error.cpp
index 5e7c4485..871159fd 100644
--- a/gjs/jsapi-util-error.cpp
+++ b/gjs/jsapi-util-error.cpp
@@ -23,9 +23,10 @@
 
 #include <config.h>
 
+#include "gi/gerror.h"
+#include "gjs/context-private.h"
 #include "jsapi-util.h"
 #include "jsapi-wrapper.h"
-#include "gi/gerror.h"
 #include "util/misc.h"
 
 #include <util/log.h>
@@ -95,10 +96,10 @@ gjs_throw_valist(JSContext       *context,
         goto out;
 
     if (error_name != NULL) {
+        const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
         JS::RootedValue name_value(context);
         if (!gjs_string_from_utf8(context, error_name, &name_value) ||
-            !gjs_object_set_property(context, new_exc, GJS_STRING_NAME,
-                                     name_value))
+            !JS_SetPropertyById(context, new_exc, atoms.name(), name_value))
             goto out;
     }
 
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index aea0040a..1641db85 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -48,87 +48,6 @@ gjs_util_error_quark (void)
     return g_quark_from_static_string ("gjs-util-error-quark");
 }
 
-bool
-gjs_object_get_property(JSContext             *cx,
-                        JS::HandleObject       obj,
-                        GjsConstString         property_name,
-                        JS::MutableHandleValue value_p)
-{
-    return JS_GetPropertyById(cx, obj,
-                              gjs_context_get_const_string(cx, property_name),
-                              value_p);
-}
-
-bool
-gjs_object_set_property(JSContext       *cx,
-                        JS::HandleObject obj,
-                        GjsConstString   property_name,
-                        JS::HandleValue  value)
-{
-    return JS_SetPropertyById(cx, obj,
-                              gjs_context_get_const_string(cx, property_name),
-                              value);
-}
-
-bool
-gjs_object_has_property(JSContext       *cx,
-                        JS::HandleObject obj,
-                        GjsConstString   property_name,
-                        bool            *found)
-{
-    return JS_HasPropertyById(cx, obj,
-                              gjs_context_get_const_string(cx, property_name),
-                              found);
-}
-
-bool
-gjs_object_define_property(JSContext       *cx,
-                           JS::HandleObject obj,
-                           GjsConstString   property_name,
-                           JS::HandleValue  value,
-                           unsigned         flags)
-{
-    return JS_DefinePropertyById(cx, obj,
-                                 gjs_context_get_const_string(cx, property_name),
-                                 value, flags);
-}
-
-bool
-gjs_object_define_property(JSContext       *cx,
-                           JS::HandleObject obj,
-                           GjsConstString   property_name,
-                           JS::HandleObject value,
-                           unsigned         flags)
-{
-    return JS_DefinePropertyById(cx, obj,
-                                 gjs_context_get_const_string(cx, property_name),
-                                 value, flags);
-}
-
-bool
-gjs_object_define_property(JSContext       *cx,
-                           JS::HandleObject obj,
-                           GjsConstString   property_name,
-                           JS::HandleString value,
-                           unsigned         flags)
-{
-    return JS_DefinePropertyById(cx, obj,
-                                 gjs_context_get_const_string(cx, property_name),
-                                 value, flags);
-}
-
-bool
-gjs_object_define_property(JSContext       *cx,
-                           JS::HandleObject obj,
-                           GjsConstString   property_name,
-                           uint32_t         value,
-                           unsigned         flags)
-{
-    return JS_DefinePropertyById(cx, obj,
-                                 gjs_context_get_const_string(cx, property_name),
-                                 value, flags);
-}
-
 static void
 throw_property_lookup_error(JSContext       *cx,
                             JS::HandleObject obj,
@@ -282,10 +201,10 @@ gjs_throw_abstract_constructor_error(JSContext    *context,
     const JSClass *proto_class;
     const char *name = "anonymous";
 
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     JS::RootedObject callee(context, &args.callee());
     JS::RootedValue prototype(context);
-    if (gjs_object_get_property(context, callee, GJS_STRING_PROTOTYPE,
-                                &prototype)) {
+    if (JS_GetPropertyById(context, callee, atoms.prototype(), &prototype)) {
         proto_class = JS_GetClass(&prototype.toObject());
         name = proto_class->name;
     }
@@ -496,6 +415,7 @@ gjs_log_exception_full(JSContext       *context,
                        JS::HandleString message)
 {
     bool is_syntax;
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
 
     JS_BeginRequest(context);
     JS::RootedObject exc_obj(context);
@@ -527,10 +447,9 @@ gjs_log_exception_full(JSContext       *context,
         JS::RootedValue js_lineNumber(context), js_fileName(context);
         unsigned lineNumber;
 
-        gjs_object_get_property(context, exc_obj, GJS_STRING_LINE_NUMBER,
-                                &js_lineNumber);
-        gjs_object_get_property(context, exc_obj, GJS_STRING_FILENAME,
-                                &js_fileName);
+        JS_GetPropertyById(context, exc_obj, atoms.line_number(),
+                           &js_lineNumber);
+        JS_GetPropertyById(context, exc_obj, atoms.file_name(), &js_fileName);
 
         JS::UniqueChars utf8_filename;
         if (js_fileName.isString()) {
@@ -555,8 +474,7 @@ gjs_log_exception_full(JSContext       *context,
         JS::RootedValue stack(context);
 
         if (exc.isObject() &&
-            gjs_object_get_property(context, exc_obj, GJS_STRING_STACK,
-                                    &stack) &&
+            JS_GetPropertyById(context, exc_obj, atoms.stack(), &stack) &&
             stack.isString()) {
             JS::RootedString str(context, stack.toString());
             utf8_stack.reset(JS_EncodeStringToUTF8(context, str));
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index c7313caa..55cfa666 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -326,93 +326,17 @@ bool gjs_eval_with_scope(JSContext             *context,
                          const char            *filename,
                          JS::MutableHandleValue retval);
 
-typedef enum {
-  GJS_STRING_CONSTRUCTOR,
-  GJS_STRING_PROTOTYPE,
-  GJS_STRING_LENGTH,
-  GJS_STRING_IMPORTS,
-  GJS_STRING_PARENT_MODULE,
-  GJS_STRING_MODULE_INIT,
-  GJS_STRING_SEARCH_PATH,
-  GJS_STRING_PRIVATE_NS_MARKER,
-  GJS_STRING_GI_MODULE,
-  GJS_STRING_GI_VERSIONS,
-  GJS_STRING_GI_OVERRIDES,
-  GJS_STRING_GOBJECT_INIT,
-  GJS_STRING_INSTANCE_INIT,
-  GJS_STRING_NEW_INTERNAL,
-  GJS_STRING_NEW,
-  GJS_STRING_MESSAGE,
-  GJS_STRING_CODE,
-  GJS_STRING_STACK,
-  GJS_STRING_FILENAME,
-  GJS_STRING_LINE_NUMBER,
-  GJS_STRING_COLUMN_NUMBER,
-  GJS_STRING_NAME,
-  GJS_STRING_X,
-  GJS_STRING_Y,
-  GJS_STRING_WIDTH,
-  GJS_STRING_HEIGHT,
-  GJS_STRING_MODULE_PATH,
-  GJS_STRING_LAST
-} GjsConstString;
-
 GJS_USE
 const char * gjs_strip_unix_shebang(const char *script,
                                     size_t     *script_len,
                                     int        *new_start_line_number);
 
-/* These four functions wrap JS_GetPropertyById(), etc., but with a
- * GjsConstString constant instead of a jsid. */
-
-bool gjs_object_get_property(JSContext             *cx,
-                             JS::HandleObject       obj,
-                             GjsConstString         property_name,
-                             JS::MutableHandleValue value_p);
-
-bool gjs_object_set_property(JSContext       *cx,
-                             JS::HandleObject obj,
-                             GjsConstString   property_name,
-                             JS::HandleValue  value);
-
-bool gjs_object_has_property(JSContext       *cx,
-                             JS::HandleObject obj,
-                             GjsConstString   property_name,
-                             bool            *found);
-
 G_END_DECLS
 
 GJS_JSAPI_RETURN_CONVENTION
 GjsAutoChar gjs_format_stack_trace(JSContext       *cx,
                                    JS::HandleObject saved_frame);
 
-bool gjs_object_define_property(JSContext       *cx,
-                                JS::HandleObject obj,
-                                GjsConstString   property_name,
-                                JS::HandleValue  value,
-                                unsigned         flags);
-
-bool gjs_object_define_property(JSContext       *cx,
-                                JS::HandleObject obj,
-                                GjsConstString   property_name,
-                                JS::HandleObject value,
-                                unsigned         flags);
-
-bool gjs_object_define_property(JSContext       *cx,
-                                JS::HandleObject obj,
-                                GjsConstString   property_name,
-                                JS::HandleString value,
-                                unsigned         flags);
-
-bool gjs_object_define_property(JSContext       *cx,
-                                JS::HandleObject obj,
-                                GjsConstString   property_name,
-                                uint32_t         value,
-                                unsigned         flags);
-
-JS::HandleId gjs_context_get_const_string(JSContext     *cx,
-                                          GjsConstString string);
-
 /* Overloaded functions, must be outside G_DECLS. More types are intended to be
  * added as the opportunity arises. */
 
@@ -457,26 +381,6 @@ bool gjs_object_require_converted_property(JSContext       *context,
                                            JS::HandleId     property_name,
                                            uint32_t        *value);
 
-/* Here, too, we have wrappers that take a GjsConstString. */
-
-template <typename T>
-GJS_JSAPI_RETURN_CONVENTION bool gjs_object_require_property(
-    JSContext* cx, JS::HandleObject obj, const char* description,
-    GjsConstString property_name, T value) {
-    return gjs_object_require_property(cx, obj, description,
-                                       gjs_context_get_const_string(cx, property_name),
-                                       value);
-}
-
-template <typename T>
-GJS_JSAPI_RETURN_CONVENTION bool gjs_object_require_converted_property(
-    JSContext* cx, JS::HandleObject obj, const char* description,
-    GjsConstString property_name, T value) {
-    return gjs_object_require_converted_property(cx, obj, description,
-                                                 gjs_context_get_const_string(cx, property_name),
-                                                 value);
-}
-
 GJS_USE std::string gjs_debug_string(JSString* str);
 GJS_USE std::string gjs_debug_symbol(JS::Symbol* const sym);
 GJS_USE std::string gjs_debug_object(JSObject* obj);
diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp
index 61c94a6d..2a169049 100644
--- a/modules/cairo-region.cpp
+++ b/modules/cairo-region.cpp
@@ -23,6 +23,7 @@
 #include <config.h>
 
 #include "gi/foreign.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-wrapper.h"
@@ -121,24 +122,25 @@ fill_rectangle(JSContext             *context,
                JS::HandleObject       obj,
                cairo_rectangle_int_t *rect)
 {
+    const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     JS::RootedValue val(context);
 
-    if (!gjs_object_get_property(context, obj, GJS_STRING_X, &val))
+    if (!JS_GetPropertyById(context, obj, atoms.x(), &val))
         return false;
     if (!JS::ToInt32(context, val, &rect->x))
         return false;
 
-    if (!gjs_object_get_property(context, obj, GJS_STRING_Y, &val))
+    if (!JS_GetPropertyById(context, obj, atoms.y(), &val))
         return false;
     if (!JS::ToInt32(context, val, &rect->y))
         return false;
 
-    if (!gjs_object_get_property(context, obj, GJS_STRING_WIDTH, &val))
+    if (!JS_GetPropertyById(context, obj, atoms.width(), &val))
         return false;
     if (!JS::ToInt32(context, val, &rect->width))
         return false;
 
-    if (!gjs_object_get_property(context, obj, GJS_STRING_HEIGHT, &val))
+    if (!JS_GetPropertyById(context, obj, atoms.height(), &val))
         return false;
     if (!JS::ToInt32(context, val, &rect->height))
         return false;


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