[gjs/master.windows: 9/9] gjs: Work around Visual Studio 2017 bug



commit 300ecfbdcd2735ec045063509dde474d30d45005
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Fri Feb 22 19:12:03 2019 +0800

    gjs: Work around Visual Studio 2017 bug
    
    It is known that codecvt_utf8_utf16 does not work when converting to
    char16_t because the symbols are somehow missing from the C++ runtime
    .lib.  So, we use the Windows APIs to do that for us, and use the
    Windows-specific std::u16string constructor using the wstring that we
    obtain using the Windows APIs.
    
    See: 
https://social.msdn.microsoft.com/Forums/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error?forum=vcgeneral

 gjs/context.cpp    |  6 ++++++
 gjs/jsapi-util.cpp | 30 ++++++++++++++++++++++++++++++
 gjs/jsapi-util.h   |  4 ++++
 gjs/module.cpp     |  6 ++++++
 4 files changed, 46 insertions(+)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index b9c5a403..7f1ce5de 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -966,8 +966,14 @@ bool GjsContextPrivate::eval_with_scope(JS::HandleObject scope_object,
     JS::CompileOptions options(m_cx);
     options.setFileAndLine(filename, start_line_number).setSourceIsLazy(true);
 
+#if defined (G_OS_WIN32) && (defined (_MSC_VER) && (_MSC_VER >= 1900))
+    std::wstring wscript = gjs_win32_vc140_utf8_to_utf16 (script);
+    std::u16string utf16_string((char16_t *)wscript.c_str());
+#else
     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
     std::u16string utf16_string = convert.from_bytes(script);
+#endif
+
     JS::SourceBufferHolder buf(utf16_string.c_str(), utf16_string.size(),
                                JS::SourceBufferHolder::NoOwnership);
 
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 11affcb4..906c5e0a 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -34,6 +34,11 @@
 #include <js/GCAPI.h>
 #include <js/Printf.h>
 
+#if defined (XP_WIN)
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
 #include "gjs/context-private.h"
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
@@ -660,3 +665,28 @@ gjs_strip_unix_shebang(const char  *script,
 
     return script;
 }
+
+#if defined (G_OS_WIN32) && (defined (_MSC_VER) && (_MSC_VER >= 1900))
+GJS_USE std::wstring
+gjs_win32_vc140_utf8_to_utf16 (const gchar *str)
+{
+/* Unfortunately Visual Studio's C++ .lib somehow did not contain the right codecvt stuff
+ * that we need to convert from utf8 to utf16 (char16_t), so we need to work around this
+ * Visual Studio bug.  Use Windows API MultiByteToWideChar() and obtain the std::u16string on
+ * the std::wstring we obtain from MultiByteToWideChar().  See:
+ * 
https://social.msdn.microsoft.com/Forums/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error?forum=vcgeneral
+ */
+    int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+    int result;
+    if (len == 0)
+        return nullptr;
+
+    std::wstring wstr(len, 0);
+    result = MultiByteToWideChar(CP_UTF8, 0, str, -1, &wstr[0], len);
+    if (result == 0)
+        return nullptr;
+
+    wstr.resize(strlen(str));
+    return wstr;
+}
+#endif
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 56c2e5a2..972ba9d5 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -363,4 +363,8 @@ GJS_USE std::string gjs_debug_id(jsid id);
 GJS_USE
 char* gjs_hyphen_to_underscore(const char* str);
 
+#if defined (G_OS_WIN32) && (defined (_MSC_VER) && (_MSC_VER >= 1900))
+GJS_USE std::wstring gjs_win32_vc140_utf8_to_utf16 (const gchar *str);
+#endif
+
 #endif  /* __GJS_JSAPI_UTIL_H__ */
diff --git a/gjs/module.cpp b/gjs/module.cpp
index 258d9b1e..d3e1fc68 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -99,8 +99,14 @@ class GjsModule {
         JS::CompileOptions options(cx);
         options.setFileAndLine(filename, line_number);
 
+#if defined (G_OS_WIN32) && (defined (_MSC_VER) && (_MSC_VER >= 1900))
+        std::wstring wscript = gjs_win32_vc140_utf8_to_utf16 (script);
+        std::u16string utf16_string((char16_t *)wscript.c_str());
+#else
         std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
         std::u16string utf16_string = convert.from_bytes(script);
+#endif
+
         JS::SourceBufferHolder buf(utf16_string.c_str(), utf16_string.size(),
                                    JS::SourceBufferHolder::NoOwnership);
 


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