diff options
author | Chun-wei Fan <fanchunwei@src.gnome.org> | 2019-02-22 19:12:03 +0800 |
---|---|---|
committer | Chun-wei Fan <fanchunwei@src.gnome.org> | 2019-03-04 15:59:54 +0800 |
commit | c455da15338edbb5d0c21a0bcc979333d5fb7be8 (patch) | |
tree | 6ba0b2a2de9e1e55b59ba8a9b04c5c2e872948d3 /gjs | |
parent | a76011f9c06bc0f8003a28825d79db85fefa1f39 (diff) | |
download | gjs-c455da15338edbb5d0c21a0bcc979333d5fb7be8.tar.gz |
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
Diffstat (limited to 'gjs')
-rw-r--r-- | gjs/context.cpp | 6 | ||||
-rw-r--r-- | gjs/jsapi-util.cpp | 28 | ||||
-rw-r--r-- | gjs/jsapi-util.h | 4 | ||||
-rw-r--r-- | gjs/module.cpp | 7 |
4 files changed, 45 insertions, 0 deletions
diff --git a/gjs/context.cpp b/gjs/context.cpp index 0f4b77f7..54c83623 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -967,8 +967,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(reinterpret_cast<const 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..72718178 100644 --- a/gjs/jsapi-util.cpp +++ b/gjs/jsapi-util.cpp @@ -34,6 +34,11 @@ #include <js/GCAPI.h> #include <js/Printf.h> +#ifdef 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,26 @@ gjs_strip_unix_shebang(const char *script, return script; } + +#if defined(G_OS_WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1900)) +/* 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 + */ +std::wstring gjs_win32_vc140_utf8_to_utf16(const char* str) { + int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0); + if (len == 0) + return nullptr; + + std::wstring wstr(len, 0); + int 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..b0f83b37 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 char* str); +#endif + #endif /* __GJS_JSAPI_UTIL_H__ */ diff --git a/gjs/module.cpp b/gjs/module.cpp index 258d9b1e..696b0a86 100644 --- a/gjs/module.cpp +++ b/gjs/module.cpp @@ -99,8 +99,15 @@ 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( + reinterpret_cast<const 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); |