[gjs: 10/25] js: Use JS::SourceText to store source code



commit 3b19f3fb5cc5b67912e9f502d3e4d0955f177bf0
Author: Philip Chimento <philip chimento gmail com>
Date:   Mon May 20 18:50:19 2019 -0700

    js: Use JS::SourceText to store source code
    
    JS::SourceText<char16_t> and JS::SourceText<mozilla::Utf8Unit> have
    replaced the JS::SourceBufferHolder API. Use the new API instead of the
    old one.
    
    It's now possible to compile UTF-8 source text directly, without
    converting it to two-byte characters first. We do this wherever
    possible, but it is currently broken when trying to execute with an
    environment object, as we do in eval_with_scope() and module imports.
    See https://bugzilla.mozilla.org/show_bug.cgi?id=1404784

 gjs/context.cpp             | 13 ++++++++++---
 gjs/engine.cpp              | 28 +++++++++-------------------
 gjs/engine.h                |  4 ++--
 gjs/global.cpp              | 19 ++++++++++++-------
 gjs/module.cpp              | 12 +++++++++---
 modules/console.cpp         | 15 ++++++++++-----
 test/gjs-test-call-args.cpp | 16 ++++++++++++++--
 7 files changed, 66 insertions(+), 41 deletions(-)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index b2b6b099..709a2b81 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -51,7 +51,10 @@
 #endif
 
 #include "gjs/jsapi-wrapper.h"
+#include "js/CompilationAndEvaluation.h"
 #include "js/GCHashTable.h"  // for WeakCache
+#include "js/SourceText.h"
+#include "js/experimental/SourceHook.h"
 
 #include "gi/object.h"
 #include "gi/private.h"
@@ -974,9 +977,13 @@ bool GjsContextPrivate::eval_with_scope(JS::HandleObject scope_object,
         eval_obj = JS_NewPlainObject(m_cx);
 
     std::u16string utf16_string = gjs_utf8_script_to_utf16(script, script_len);
-
-    JS::SourceBufferHolder buf(utf16_string.c_str(), utf16_string.size(),
-                               JS::SourceBufferHolder::NoOwnership);
+    // COMPAT: This could use JS::SourceText<mozilla::Utf8Unit> directly,
+    // but that messes up code coverage. See bug
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=1404784
+    JS::SourceText<char16_t> buf;
+    if (!buf.init(m_cx, utf16_string.c_str(), utf16_string.size(),
+                  JS::SourceOwnership::Borrowed))
+        return false;
 
     JS::RootedObjectVector scope_chain(m_cx);
     if (!scope_chain.append(eval_obj)) {
diff --git a/gjs/engine.cpp b/gjs/engine.cpp
index 0bded2a1..6d7ad940 100644
--- a/gjs/engine.cpp
+++ b/gjs/engine.cpp
@@ -36,6 +36,7 @@
 #include "gjs/jsapi-wrapper.h"
 #include "js/Initialization.h"  // for JS_Init, JS_ShutDown
 #include "js/Warnings.h"
+#include "js/experimental/SourceHook.h"
 #include "mozilla/UniquePtr.h"
 
 #include "gi/object.h"
@@ -215,36 +216,25 @@ static void on_promise_unhandled_rejection(
     gjs->register_unhandled_promise_rejection(id, std::move(stack));
 }
 
-bool gjs_load_internal_source(JSContext* cx, const char* filename,
-                              JS::UniqueTwoByteChars* src, size_t* length) {
+bool gjs_load_internal_source(JSContext* cx, const char* filename, char** src,
+                              size_t* length) {
     GError* error = nullptr;
     const char* path = filename + 11;  // len("resource://")
-    GjsAutoPointer<GBytes, GBytes, g_bytes_unref> script_bytes;
-    script_bytes =
+    GBytes* script_bytes =
         g_resources_lookup_data(path, G_RESOURCE_LOOKUP_FLAGS_NONE, &error);
     if (!script_bytes)
         return gjs_throw_gerror_message(cx, error);
 
-    size_t script_len;
-    const void* script_data = g_bytes_get_data(script_bytes, &script_len);
-    JS::ConstUTF8CharsZ script(static_cast<const char*>(script_data),
-                               script_len);
-    JS::TwoByteCharsZ chs = JS::UTF8CharsToNewTwoByteCharsZ(cx, script, length);
-    if (!chs)
-        return false;
-
-    src->reset(chs.get());
+    *src = static_cast<char*>(g_bytes_unref_to_data(script_bytes, length));
     return true;
 }
 
 class GjsSourceHook : public js::SourceHook {
-    bool load(JSContext* cx, const char* filename, char16_t** src,
+    bool load(JSContext* cx, const char* filename,
+              char16_t** two_byte_source G_GNUC_UNUSED, char** utf8_source,
               size_t* length) {
-        JS::UniqueTwoByteChars chars;
-        if (!gjs_load_internal_source(cx, filename, &chars, length))
-            return false;
-        *src = chars.release();  // caller owns, per documentation of SourceHook
-        return true;
+        // caller owns the source, per documentation of SourceHook
+        return gjs_load_internal_source(cx, filename, utf8_source, length);
     }
 };
 
diff --git a/gjs/engine.h b/gjs/engine.h
index a87ee273..c6ec5794 100644
--- a/gjs/engine.h
+++ b/gjs/engine.h
@@ -32,7 +32,7 @@ class GjsContextPrivate;
 
 JSContext* gjs_create_js_context(GjsContextPrivate* uninitialized_gjs);
 
-bool gjs_load_internal_source(JSContext* cx, const char* filename,
-                              JS::UniqueTwoByteChars* src, size_t* length);
+bool gjs_load_internal_source(JSContext* cx, const char* filename, char** src,
+                              size_t* length);
 
 #endif  // GJS_ENGINE_H_
diff --git a/gjs/global.cpp b/gjs/global.cpp
index 41d9cba2..20a448bd 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -28,6 +28,8 @@
 #include <glib.h>
 
 #include "gjs/jsapi-wrapper.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceText.h"
 
 #include "gjs/atoms.h"
 #include "gjs/context-private.h"
@@ -47,17 +49,20 @@ run_bootstrap(JSContext       *cx,
     JSAutoRealm ar(cx, global);
 
     JS::CompileOptions options(cx);
-    options.setUTF8(true)
-           .setFileAndLine(uri, 1)
-           .setSourceIsLazy(true);
+    options.setFileAndLine(uri, 1).setSourceIsLazy(true);
 
-    JS::UniqueTwoByteChars script;
+    char* script;
     size_t script_len;
-    if (!gjs_load_internal_source(cx, uri.get(), &script, &script_len))
+    if (!gjs_load_internal_source(cx, uri, &script, &script_len))
         return false;
 
-    JS::RootedScript compiled_script(cx);
-    if (!JS::Compile(cx, options, script.get(), script_len, &compiled_script))
+    JS::SourceText<mozilla::Utf8Unit> source;
+    if (!source.init(cx, script, script_len,
+                     JS::SourceOwnership::TakeOwnership))
+        return false;
+
+    JS::RootedScript compiled_script(cx, JS::Compile(cx, options, source));
+    if (!compiled_script)
         return false;
 
     JS::RootedValue ignored(cx);
diff --git a/gjs/module.cpp b/gjs/module.cpp
index f08cb644..58b51df3 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -30,6 +30,8 @@
 #include <glib.h>
 
 #include "gjs/jsapi-wrapper.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceText.h"
 
 #include "gjs/context-private.h"
 #include "gjs/jsapi-util.h"
@@ -97,9 +99,13 @@ class GjsModule {
                          const char* filename) {
         std::u16string utf16_string =
             gjs_utf8_script_to_utf16(script, script_len);
-
-        JS::SourceBufferHolder buf(utf16_string.c_str(), utf16_string.size(),
-                                   JS::SourceBufferHolder::NoOwnership);
+        // COMPAT: This could use JS::SourceText<mozilla::Utf8Unit> directly,
+        // but that messes up code coverage. See bug
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=1404784
+        JS::SourceText<char16_t> buf;
+        if (!buf.init(cx, utf16_string.c_str(), utf16_string.size(),
+                      JS::SourceOwnership::Borrowed))
+            return false;
 
         JS::RootedObjectVector scope_chain(cx);
         if (!scope_chain.append(module)) {
diff --git a/modules/console.cpp b/modules/console.cpp
index 723954a5..607d3ec0 100644
--- a/modules/console.cpp
+++ b/modules/console.cpp
@@ -52,6 +52,8 @@
 #include <glib/gprintf.h>  // for g_fprintf
 
 #include "gjs/jsapi-wrapper.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceText.h"
 #include "js/Warnings.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
@@ -271,12 +273,15 @@ gjs_console_eval_and_print(JSContext  *cx,
                            size_t      length,
                            int         lineno)
 {
+    JS::SourceText<mozilla::Utf8Unit> source;
+    if (!source.init(cx, bytes, length, JS::SourceOwnership::Borrowed))
+        return false;
+
     JS::CompileOptions options(cx);
-    options.setUTF8(true)
-           .setFileAndLine("typein", lineno);
+    options.setFileAndLine("typein", lineno);
 
     JS::RootedValue result(cx);
-    if (!JS::Evaluate(cx, options, bytes, length, &result)) {
+    if (!JS::Evaluate(cx, options, source, &result)) {
         if (!JS_IsExceptionPending(cx))
             return false;
     }
@@ -332,8 +337,8 @@ gjs_console_interact(JSContext *context,
             g_string_append(buffer, temp_buf);
             g_free(temp_buf);
             lineno++;
-        } while (!JS_BufferIsCompilableUnit(context, global,
-                                            buffer->str, buffer->len));
+        } while (!JS_Utf8BufferIsCompilableUnit(context, global, buffer->str,
+                                                buffer->len));
 
         bool ok;
         {
diff --git a/test/gjs-test-call-args.cpp b/test/gjs-test-call-args.cpp
index 3e681573..3c5c3219 100644
--- a/test/gjs-test-call-args.cpp
+++ b/test/gjs-test-call-args.cpp
@@ -4,6 +4,8 @@
 #include <glib.h>
 
 #include "gjs/jsapi-wrapper.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/SourceText.h"
 
 #include "gjs/jsapi-util-args.h"
 #include "gjs/jsapi-util.h"
@@ -273,11 +275,16 @@ run_code(GjsUnitTestFixture *fx,
 {
     const char *script = (const char *) code;
 
+    JS::SourceText<mozilla::Utf8Unit> source;
+    bool ok = source.init(fx->cx, script, strlen(script),
+                          JS::SourceOwnership::Borrowed);
+    g_assert_true(ok);
+
     JS::CompileOptions options(fx->cx);
     options.setFileAndLine("unit test", 1);
 
     JS::RootedValue ignored(fx->cx);
-    bool ok = JS::Evaluate(fx->cx, options, script, strlen(script), &ignored);
+    ok = JS::Evaluate(fx->cx, options, source, &ignored);
 
     g_assert_null(gjs_test_get_exception_message(fx->cx));
     g_assert_true(ok);
@@ -289,11 +296,16 @@ run_code_expect_exception(GjsUnitTestFixture *fx,
 {
     const char *script = (const char *) code;
 
+    JS::SourceText<mozilla::Utf8Unit> source;
+    bool ok = source.init(fx->cx, script, strlen(script),
+                          JS::SourceOwnership::Borrowed);
+    g_assert_true(ok);
+
     JS::CompileOptions options(fx->cx);
     options.setFileAndLine("unit test", 1);
 
     JS::RootedValue ignored(fx->cx);
-    bool ok = JS::Evaluate(fx->cx, options, script, strlen(script), &ignored);
+    ok = JS::Evaluate(fx->cx, options, source, &ignored);
     g_assert_false(ok);
     GjsAutoChar message = gjs_test_get_exception_message(fx->cx);
     g_assert_nonnull(message);


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