refactor: use constexpr lookup tables in gin helper (#38818)
* feat: add gin_helper::FromV8WithLookup() feat: add gin_helper::FromV8WithLowerLookup() * refactor: use constexpr lookup table in gin Converters
This commit is contained in:
		
					parent
					
						
							
								41ab5f327f
							
						
					
				
			
			
				commit
				
					
						97132ece33
					
				
			
		
					 6 changed files with 255 additions and 400 deletions
				
			
		|  | @ -141,40 +141,25 @@ struct Converter<JumpListItem::Type> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Local<v8::Value> val, |                      v8::Local<v8::Value> val, | ||||||
|                      JumpListItem::Type* out) { |                      JumpListItem::Type* out) { | ||||||
|     std::string item_type; |     return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|     if (!ConvertFromV8(isolate, val, &item_type)) |  | ||||||
|       return false; |  | ||||||
| 
 |  | ||||||
|     if (item_type == "task") |  | ||||||
|       *out = JumpListItem::Type::kTask; |  | ||||||
|     else if (item_type == "separator") |  | ||||||
|       *out = JumpListItem::Type::kSeparator; |  | ||||||
|     else if (item_type == "file") |  | ||||||
|       *out = JumpListItem::Type::kFile; |  | ||||||
|     else |  | ||||||
|       return false; |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, |   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, | ||||||
|                                    JumpListItem::Type val) { |                                    JumpListItem::Type val) { | ||||||
|     std::string item_type; |     for (const auto& [name, item_val] : Lookup) | ||||||
|     switch (val) { |       if (item_val == val) | ||||||
|       case JumpListItem::Type::kTask: |         return gin::ConvertToV8(isolate, name); | ||||||
|         item_type = "task"; |  | ||||||
|         break; |  | ||||||
| 
 | 
 | ||||||
|       case JumpListItem::Type::kSeparator: |     return gin::ConvertToV8(isolate, ""); | ||||||
|         item_type = "separator"; |   } | ||||||
|         break; |  | ||||||
| 
 | 
 | ||||||
|       case JumpListItem::Type::kFile: |  private: | ||||||
|         item_type = "file"; |   static constexpr auto Lookup = | ||||||
|         break; |       base::MakeFixedFlatMapSorted<base::StringPiece, JumpListItem::Type>({ | ||||||
|     } |           {"file", JumpListItem::Type::kFile}, | ||||||
|     return gin::ConvertToV8(isolate, item_type); |           {"separator", JumpListItem::Type::kSeparator}, | ||||||
|   } |           {"task", JumpListItem::Type::kTask}, | ||||||
|  |       }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <> | template <> | ||||||
|  | @ -247,46 +232,26 @@ struct Converter<JumpListCategory::Type> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Local<v8::Value> val, |                      v8::Local<v8::Value> val, | ||||||
|                      JumpListCategory::Type* out) { |                      JumpListCategory::Type* out) { | ||||||
|     std::string category_type; |     return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|     if (!ConvertFromV8(isolate, val, &category_type)) |  | ||||||
|       return false; |  | ||||||
| 
 |  | ||||||
|     if (category_type == "tasks") |  | ||||||
|       *out = JumpListCategory::Type::kTasks; |  | ||||||
|     else if (category_type == "frequent") |  | ||||||
|       *out = JumpListCategory::Type::kFrequent; |  | ||||||
|     else if (category_type == "recent") |  | ||||||
|       *out = JumpListCategory::Type::kRecent; |  | ||||||
|     else if (category_type == "custom") |  | ||||||
|       *out = JumpListCategory::Type::kCustom; |  | ||||||
|     else |  | ||||||
|       return false; |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, |   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, | ||||||
|                                    JumpListCategory::Type val) { |                                    JumpListCategory::Type val) { | ||||||
|     std::string category_type; |     for (const auto& [name, type_val] : Lookup) | ||||||
|     switch (val) { |       if (type_val == val) | ||||||
|       case JumpListCategory::Type::kTasks: |         return gin::ConvertToV8(isolate, name); | ||||||
|         category_type = "tasks"; |  | ||||||
|         break; |  | ||||||
| 
 | 
 | ||||||
|       case JumpListCategory::Type::kFrequent: |     return gin::ConvertToV8(isolate, ""); | ||||||
|         category_type = "frequent"; |  | ||||||
|         break; |  | ||||||
| 
 |  | ||||||
|       case JumpListCategory::Type::kRecent: |  | ||||||
|         category_type = "recent"; |  | ||||||
|         break; |  | ||||||
| 
 |  | ||||||
|       case JumpListCategory::Type::kCustom: |  | ||||||
|         category_type = "custom"; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     return gin::ConvertToV8(isolate, category_type); |  | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |  private: | ||||||
|  |   static constexpr auto Lookup = | ||||||
|  |       base::MakeFixedFlatMapSorted<base::StringPiece, JumpListCategory::Type>({ | ||||||
|  |           {"custom", JumpListCategory::Type::kCustom}, | ||||||
|  |           {"frequent", JumpListCategory::Type::kFrequent}, | ||||||
|  |           {"recent", JumpListCategory::Type::kRecent}, | ||||||
|  |           {"tasks", JumpListCategory::Type::kTasks}, | ||||||
|  |       }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <> | template <> | ||||||
|  | @ -440,20 +405,13 @@ struct Converter<net::SecureDnsMode> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Local<v8::Value> val, |                      v8::Local<v8::Value> val, | ||||||
|                      net::SecureDnsMode* out) { |                      net::SecureDnsMode* out) { | ||||||
|     std::string s; |     static constexpr auto Lookup = | ||||||
|     if (!ConvertFromV8(isolate, val, &s)) |         base::MakeFixedFlatMapSorted<base::StringPiece, net::SecureDnsMode>({ | ||||||
|       return false; |             {"automatic", net::SecureDnsMode::kAutomatic}, | ||||||
|     if (s == "off") { |             {"off", net::SecureDnsMode::kOff}, | ||||||
|       *out = net::SecureDnsMode::kOff; |             {"secure", net::SecureDnsMode::kSecure}, | ||||||
|       return true; |         }); | ||||||
|     } else if (s == "automatic") { |     return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|       *out = net::SecureDnsMode::kAutomatic; |  | ||||||
|       return true; |  | ||||||
|     } else if (s == "secure") { |  | ||||||
|       *out = net::SecureDnsMode::kSecure; |  | ||||||
|       return true; |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| }  // namespace gin
 | }  // namespace gin
 | ||||||
|  |  | ||||||
|  | @ -62,20 +62,16 @@ struct Converter<network::mojom::CredentialsMode> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Local<v8::Value> val, |                      v8::Local<v8::Value> val, | ||||||
|                      network::mojom::CredentialsMode* out) { |                      network::mojom::CredentialsMode* out) { | ||||||
|     std::string mode; |     using Val = network::mojom::CredentialsMode; | ||||||
|     if (!ConvertFromV8(isolate, val, &mode)) |     static constexpr auto Lookup = | ||||||
|       return false; |         base::MakeFixedFlatMapSorted<base::StringPiece, Val>({ | ||||||
|     if (mode == "omit") |             {"include", Val::kInclude}, | ||||||
|       *out = network::mojom::CredentialsMode::kOmit; |             {"omit", Val::kOmit}, | ||||||
|     else if (mode == "include") |             // Note: This only makes sense if the request
 | ||||||
|       *out = network::mojom::CredentialsMode::kInclude; |             // specifies the "origin" option.
 | ||||||
|     else if (mode == "same-origin") |             {"same-origin", Val::kSameOrigin}, | ||||||
|       // Note: This only makes sense if the request specifies the "origin"
 |         }); | ||||||
|       // option.
 |     return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|       *out = network::mojom::CredentialsMode::kSameOrigin; |  | ||||||
|     else |  | ||||||
|       return false; |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -84,25 +80,17 @@ struct Converter<blink::mojom::FetchCacheMode> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Local<v8::Value> val, |                      v8::Local<v8::Value> val, | ||||||
|                      blink::mojom::FetchCacheMode* out) { |                      blink::mojom::FetchCacheMode* out) { | ||||||
|     std::string cache; |     using Val = blink::mojom::FetchCacheMode; | ||||||
|     if (!ConvertFromV8(isolate, val, &cache)) |     static constexpr auto Lookup = | ||||||
|       return false; |         base::MakeFixedFlatMapSorted<base::StringPiece, Val>({ | ||||||
|     if (cache == "default") { |             {"default", Val::kDefault}, | ||||||
|       *out = blink::mojom::FetchCacheMode::kDefault; |             {"force-cache", Val::kForceCache}, | ||||||
|     } else if (cache == "no-store") { |             {"no-cache", Val::kValidateCache}, | ||||||
|       *out = blink::mojom::FetchCacheMode::kNoStore; |             {"no-store", Val::kNoStore}, | ||||||
|     } else if (cache == "reload") { |             {"only-if-cached", Val::kOnlyIfCached}, | ||||||
|       *out = blink::mojom::FetchCacheMode::kBypassCache; |             {"reload", Val::kBypassCache}, | ||||||
|     } else if (cache == "no-cache") { |         }); | ||||||
|       *out = blink::mojom::FetchCacheMode::kValidateCache; |     return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|     } else if (cache == "force-cache") { |  | ||||||
|       *out = blink::mojom::FetchCacheMode::kForceCache; |  | ||||||
|     } else if (cache == "only-if-cached") { |  | ||||||
|       *out = blink::mojom::FetchCacheMode::kOnlyIfCached; |  | ||||||
|     } else { |  | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -111,42 +99,24 @@ struct Converter<net::ReferrerPolicy> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Local<v8::Value> val, |                      v8::Local<v8::Value> val, | ||||||
|                      net::ReferrerPolicy* out) { |                      net::ReferrerPolicy* out) { | ||||||
|     std::string referrer_policy; |     using Val = net::ReferrerPolicy; | ||||||
|     if (!ConvertFromV8(isolate, val, &referrer_policy)) |     // clang-format off
 | ||||||
|       return false; |     static constexpr auto Lookup = | ||||||
|     if (base::CompareCaseInsensitiveASCII(referrer_policy, "no-referrer") == |         base::MakeFixedFlatMapSorted<base::StringPiece, Val>({ | ||||||
|         0) { |             {"", Val::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN}, | ||||||
|       *out = net::ReferrerPolicy::NO_REFERRER; |             {"no-referrer", Val::NO_REFERRER}, | ||||||
|     } else if (base::CompareCaseInsensitiveASCII( |             {"no-referrer-when-downgrade", Val::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE}, | ||||||
|                    referrer_policy, "no-referrer-when-downgrade") == 0) { |             {"origin", Val::ORIGIN}, | ||||||
|       *out = net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE; |             {"origin-when-cross-origin", Val::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN}, | ||||||
|     } else if (base::CompareCaseInsensitiveASCII(referrer_policy, "origin") == |             {"same-origin", Val::CLEAR_ON_TRANSITION_CROSS_ORIGIN}, | ||||||
|                0) { |             {"strict-origin", Val:: ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE}, | ||||||
|       *out = net::ReferrerPolicy::ORIGIN; |             {"strict-origin-when-cross-origin", Val::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN}, | ||||||
|     } else if (base::CompareCaseInsensitiveASCII( |             {"unsafe-url", Val::NEVER_CLEAR}, | ||||||
|                    referrer_policy, "origin-when-cross-origin") == 0) { |         }); | ||||||
|       *out = net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN; |     // clang-format on
 | ||||||
|     } else if (base::CompareCaseInsensitiveASCII(referrer_policy, |     return FromV8WithLowerLookup(isolate, val, Lookup, out); | ||||||
|                                                  "unsafe-url") == 0) { |  | ||||||
|       *out = net::ReferrerPolicy::NEVER_CLEAR; |  | ||||||
|     } else if (base::CompareCaseInsensitiveASCII(referrer_policy, |  | ||||||
|                                                  "same-origin") == 0) { |  | ||||||
|       *out = net::ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN; |  | ||||||
|     } else if (base::CompareCaseInsensitiveASCII(referrer_policy, |  | ||||||
|                                                  "strict-origin") == 0) { |  | ||||||
|       *out = net::ReferrerPolicy:: |  | ||||||
|           ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE; |  | ||||||
|     } else if (referrer_policy == "" || |  | ||||||
|                base::CompareCaseInsensitiveASCII( |  | ||||||
|                    referrer_policy, "strict-origin-when-cross-origin") == 0) { |  | ||||||
|       *out = net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN; |  | ||||||
|     } else { |  | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
| }  // namespace gin
 | }  // namespace gin
 | ||||||
| 
 | 
 | ||||||
| namespace electron::api { | namespace electron::api { | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| #include <utility> | #include <utility> | ||||||
| 
 | 
 | ||||||
| #include "base/containers/contains.h" | #include "base/containers/contains.h" | ||||||
|  | #include "base/containers/fixed_flat_map.h" | ||||||
| #include "base/memory/raw_ptr.h" | #include "base/memory/raw_ptr.h" | ||||||
| #include "base/stl_util.h" | #include "base/stl_util.h" | ||||||
| #include "base/task/sequenced_task_runner.h" | #include "base/task/sequenced_task_runner.h" | ||||||
|  | @ -31,54 +32,34 @@ | ||||||
| #include "shell/common/gin_converters/value_converter.h" | #include "shell/common/gin_converters/value_converter.h" | ||||||
| #include "shell/common/gin_helper/dictionary.h" | #include "shell/common/gin_helper/dictionary.h" | ||||||
| 
 | 
 | ||||||
|  | static constexpr auto ResourceTypes = | ||||||
|  |     base::MakeFixedFlatMapSorted<base::StringPiece, | ||||||
|  |                                  extensions::WebRequestResourceType>({ | ||||||
|  |         {"cspReport", extensions::WebRequestResourceType::CSP_REPORT}, | ||||||
|  |         {"font", extensions::WebRequestResourceType::FONT}, | ||||||
|  |         {"image", extensions::WebRequestResourceType::IMAGE}, | ||||||
|  |         {"mainFrame", extensions::WebRequestResourceType::MAIN_FRAME}, | ||||||
|  |         {"media", extensions::WebRequestResourceType::MEDIA}, | ||||||
|  |         {"object", extensions::WebRequestResourceType::OBJECT}, | ||||||
|  |         {"ping", extensions::WebRequestResourceType::PING}, | ||||||
|  |         {"script", extensions::WebRequestResourceType::SCRIPT}, | ||||||
|  |         {"stylesheet", extensions::WebRequestResourceType::STYLESHEET}, | ||||||
|  |         {"subFrame", extensions::WebRequestResourceType::SUB_FRAME}, | ||||||
|  |         {"webSocket", extensions::WebRequestResourceType::WEB_SOCKET}, | ||||||
|  |         {"xhr", extensions::WebRequestResourceType::XHR}, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
| namespace gin { | namespace gin { | ||||||
| 
 | 
 | ||||||
| template <> | template <> | ||||||
| struct Converter<extensions::WebRequestResourceType> { | struct Converter<extensions::WebRequestResourceType> { | ||||||
|   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, |   static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, | ||||||
|                                    extensions::WebRequestResourceType type) { |                                    extensions::WebRequestResourceType type) { | ||||||
|     const char* result; |     for (const auto& [name, val] : ResourceTypes) | ||||||
|     switch (type) { |       if (type == val) | ||||||
|       case extensions::WebRequestResourceType::MAIN_FRAME: |         return StringToV8(isolate, name); | ||||||
|         result = "mainFrame"; | 
 | ||||||
|         break; |     return StringToV8(isolate, "other"); | ||||||
|       case extensions::WebRequestResourceType::SUB_FRAME: |  | ||||||
|         result = "subFrame"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::STYLESHEET: |  | ||||||
|         result = "stylesheet"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::SCRIPT: |  | ||||||
|         result = "script"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::IMAGE: |  | ||||||
|         result = "image"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::FONT: |  | ||||||
|         result = "font"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::OBJECT: |  | ||||||
|         result = "object"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::XHR: |  | ||||||
|         result = "xhr"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::PING: |  | ||||||
|         result = "ping"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::CSP_REPORT: |  | ||||||
|         result = "cspReport"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::MEDIA: |  | ||||||
|         result = "media"; |  | ||||||
|         break; |  | ||||||
|       case extensions::WebRequestResourceType::WEB_SOCKET: |  | ||||||
|         result = "webSocket"; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         result = "other"; |  | ||||||
|     } |  | ||||||
|     return StringToV8(isolate, result); |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -96,35 +77,12 @@ struct UserData : public base::SupportsUserData::Data { | ||||||
|   raw_ptr<WebRequest> data; |   raw_ptr<WebRequest> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extensions::WebRequestResourceType ParseResourceType(const std::string& value) { | extensions::WebRequestResourceType ParseResourceType(base::StringPiece value) { | ||||||
|   if (value == "mainFrame") { |   if (const auto* iter = ResourceTypes.find(value); iter != ResourceTypes.end()) | ||||||
|     return extensions::WebRequestResourceType::MAIN_FRAME; |     return iter->second; | ||||||
|   } else if (value == "subFrame") { | 
 | ||||||
|     return extensions::WebRequestResourceType::SUB_FRAME; |  | ||||||
|   } else if (value == "stylesheet") { |  | ||||||
|     return extensions::WebRequestResourceType::STYLESHEET; |  | ||||||
|   } else if (value == "script") { |  | ||||||
|     return extensions::WebRequestResourceType::SCRIPT; |  | ||||||
|   } else if (value == "image") { |  | ||||||
|     return extensions::WebRequestResourceType::IMAGE; |  | ||||||
|   } else if (value == "font") { |  | ||||||
|     return extensions::WebRequestResourceType::FONT; |  | ||||||
|   } else if (value == "object") { |  | ||||||
|     return extensions::WebRequestResourceType::OBJECT; |  | ||||||
|   } else if (value == "xhr") { |  | ||||||
|     return extensions::WebRequestResourceType::XHR; |  | ||||||
|   } else if (value == "ping") { |  | ||||||
|     return extensions::WebRequestResourceType::PING; |  | ||||||
|   } else if (value == "cspReport") { |  | ||||||
|     return extensions::WebRequestResourceType::CSP_REPORT; |  | ||||||
|   } else if (value == "media") { |  | ||||||
|     return extensions::WebRequestResourceType::MEDIA; |  | ||||||
|   } else if (value == "webSocket") { |  | ||||||
|     return extensions::WebRequestResourceType::WEB_SOCKET; |  | ||||||
|   } else { |  | ||||||
|   return extensions::WebRequestResourceType::OTHER; |   return extensions::WebRequestResourceType::OTHER; | ||||||
| } | } | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| // Convert HttpResponseHeaders to V8.
 | // Convert HttpResponseHeaders to V8.
 | ||||||
| //
 | //
 | ||||||
|  |  | ||||||
|  | @ -8,12 +8,14 @@ | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
|  | #include "base/containers/fixed_flat_map.h" | ||||||
| #include "base/strings/string_util.h" | #include "base/strings/string_util.h" | ||||||
| #include "base/strings/utf_string_conversions.h" | #include "base/strings/utf_string_conversions.h" | ||||||
| #include "gin/converter.h" | #include "gin/converter.h" | ||||||
| #include "gin/data_object_builder.h" | #include "gin/data_object_builder.h" | ||||||
| #include "shell/common/gin_converters/gfx_converter.h" | #include "shell/common/gin_converters/gfx_converter.h" | ||||||
| #include "shell/common/gin_converters/gurl_converter.h" | #include "shell/common/gin_converters/gurl_converter.h" | ||||||
|  | #include "shell/common/gin_converters/std_converter.h" | ||||||
| #include "shell/common/gin_converters/value_converter.h" | #include "shell/common/gin_converters/value_converter.h" | ||||||
| #include "shell/common/gin_helper/dictionary.h" | #include "shell/common/gin_helper/dictionary.h" | ||||||
| #include "shell/common/keyboard_util.h" | #include "shell/common/keyboard_util.h" | ||||||
|  | @ -130,86 +132,77 @@ struct Converter<blink::WebMouseEvent::Button> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Handle<v8::Value> val, |                      v8::Handle<v8::Value> val, | ||||||
|                      blink::WebMouseEvent::Button* out) { |                      blink::WebMouseEvent::Button* out) { | ||||||
|     std::string button = base::ToLowerASCII(gin::V8ToString(isolate, val)); |     using Val = blink::WebMouseEvent::Button; | ||||||
|     if (button == "left") |     static constexpr auto Lookup = | ||||||
|       *out = blink::WebMouseEvent::Button::kLeft; |         base::MakeFixedFlatMapSorted<base::StringPiece, Val>({ | ||||||
|     else if (button == "middle") |             {"left", Val::kLeft}, | ||||||
|       *out = blink::WebMouseEvent::Button::kMiddle; |             {"middle", Val::kMiddle}, | ||||||
|     else if (button == "right") |             {"right", Val::kRight}, | ||||||
|       *out = blink::WebMouseEvent::Button::kRight; |         }); | ||||||
|     else |     return FromV8WithLowerLookup(isolate, val, Lookup, out); | ||||||
|       return false; |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // clang-format off
 | ||||||
|  | 
 | ||||||
|  | // these are the modifier names we both accept and return
 | ||||||
|  | static constexpr auto Modifiers = | ||||||
|  |     base::MakeFixedFlatMapSorted<base::StringPiece, blink::WebInputEvent::Modifiers>({ | ||||||
|  |         {"alt", blink::WebInputEvent::Modifiers::kAltKey}, | ||||||
|  |         {"capslock", blink::WebInputEvent::Modifiers::kCapsLockOn}, | ||||||
|  |         {"control", blink::WebInputEvent::Modifiers::kControlKey}, | ||||||
|  |         {"isautorepeat", blink::WebInputEvent::Modifiers::kIsAutoRepeat}, | ||||||
|  |         {"iskeypad", blink::WebInputEvent::Modifiers::kIsKeyPad}, | ||||||
|  |         {"left", blink::WebInputEvent::Modifiers::kIsLeft}, | ||||||
|  |         {"leftbuttondown", blink::WebInputEvent::Modifiers::kLeftButtonDown}, | ||||||
|  |         {"meta", blink::WebInputEvent::Modifiers::kMetaKey}, | ||||||
|  |         {"middlebuttondown", blink::WebInputEvent::Modifiers::kMiddleButtonDown}, | ||||||
|  |         {"numlock", blink::WebInputEvent::Modifiers::kNumLockOn}, | ||||||
|  |         {"right", blink::WebInputEvent::Modifiers::kIsRight}, | ||||||
|  |         {"rightbuttondown", blink::WebInputEvent::Modifiers::kRightButtonDown}, | ||||||
|  |         {"shift", blink::WebInputEvent::Modifiers::kShiftKey}, | ||||||
|  |         // TODO(nornagon): the rest of the modifiers
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // these are the modifier names we accept but do not return
 | ||||||
|  | static constexpr auto ModifierAliases = | ||||||
|  |     base::MakeFixedFlatMapSorted<base::StringPiece, blink::WebInputEvent::Modifiers>({ | ||||||
|  |         {"cmd", blink::WebInputEvent::Modifiers::kMetaKey}, | ||||||
|  |         {"command", blink::WebInputEvent::Modifiers::kMetaKey}, | ||||||
|  |         {"ctrl", blink::WebInputEvent::Modifiers::kControlKey}, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | static constexpr auto ReferrerPolicies = | ||||||
|  |     base::MakeFixedFlatMapSorted<base::StringPiece, network::mojom::ReferrerPolicy>({ | ||||||
|  |         {"default", network::mojom::ReferrerPolicy::kDefault}, | ||||||
|  |         {"no-referrer", network::mojom::ReferrerPolicy::kNever}, | ||||||
|  |         {"no-referrer-when-downgrade", network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade}, | ||||||
|  |         {"origin", network::mojom::ReferrerPolicy::kOrigin}, | ||||||
|  |         {"same-origin", network::mojom::ReferrerPolicy::kSameOrigin}, | ||||||
|  |         {"strict-origin", network::mojom::ReferrerPolicy::kStrictOrigin}, | ||||||
|  |         {"strict-origin-when-cross-origin", network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin}, | ||||||
|  |         {"unsafe-url", network::mojom::ReferrerPolicy::kAlways}, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | // clang-format on
 | ||||||
|  | 
 | ||||||
| template <> | template <> | ||||||
| struct Converter<blink::WebInputEvent::Modifiers> { | struct Converter<blink::WebInputEvent::Modifiers> { | ||||||
|   static bool FromV8(v8::Isolate* isolate, |   static bool FromV8(v8::Isolate* isolate, | ||||||
|                      v8::Handle<v8::Value> val, |                      v8::Handle<v8::Value> val, | ||||||
|                      blink::WebInputEvent::Modifiers* out) { |                      blink::WebInputEvent::Modifiers* out) { | ||||||
|     std::string modifier = base::ToLowerASCII(gin::V8ToString(isolate, val)); |     return FromV8WithLowerLookup(isolate, val, Modifiers, out) || | ||||||
|     if (modifier == "shift") |            FromV8WithLowerLookup(isolate, val, ModifierAliases, out); | ||||||
|       *out = blink::WebInputEvent::Modifiers::kShiftKey; |  | ||||||
|     else if (modifier == "control" || modifier == "ctrl") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kControlKey; |  | ||||||
|     else if (modifier == "alt") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kAltKey; |  | ||||||
|     else if (modifier == "meta" || modifier == "command" || modifier == "cmd") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kMetaKey; |  | ||||||
|     else if (modifier == "iskeypad") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kIsKeyPad; |  | ||||||
|     else if (modifier == "isautorepeat") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kIsAutoRepeat; |  | ||||||
|     else if (modifier == "leftbuttondown") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kLeftButtonDown; |  | ||||||
|     else if (modifier == "middlebuttondown") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kMiddleButtonDown; |  | ||||||
|     else if (modifier == "rightbuttondown") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kRightButtonDown; |  | ||||||
|     else if (modifier == "capslock") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kCapsLockOn; |  | ||||||
|     else if (modifier == "numlock") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kNumLockOn; |  | ||||||
|     else if (modifier == "left") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kIsLeft; |  | ||||||
|     else if (modifier == "right") |  | ||||||
|       *out = blink::WebInputEvent::Modifiers::kIsRight; |  | ||||||
|     // TODO(nornagon): the rest of the modifiers
 |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| std::vector<base::StringPiece> ModifiersToArray(int modifiers) { | std::vector<base::StringPiece> ModifiersToArray(int modifiers) { | ||||||
|   using Modifiers = blink::WebInputEvent::Modifiers; |  | ||||||
|   std::vector<base::StringPiece> modifier_strings; |   std::vector<base::StringPiece> modifier_strings; | ||||||
|   if (modifiers & Modifiers::kShiftKey) | 
 | ||||||
|     modifier_strings.push_back("shift"); |   for (const auto& [name, mask] : Modifiers) | ||||||
|   if (modifiers & Modifiers::kControlKey) |     if (mask & modifiers) | ||||||
|     modifier_strings.push_back("control"); |       modifier_strings.emplace_back(name); | ||||||
|   if (modifiers & Modifiers::kAltKey) | 
 | ||||||
|     modifier_strings.push_back("alt"); |  | ||||||
|   if (modifiers & Modifiers::kMetaKey) |  | ||||||
|     modifier_strings.push_back("meta"); |  | ||||||
|   if (modifiers & Modifiers::kIsKeyPad) |  | ||||||
|     modifier_strings.push_back("iskeypad"); |  | ||||||
|   if (modifiers & Modifiers::kIsAutoRepeat) |  | ||||||
|     modifier_strings.push_back("isautorepeat"); |  | ||||||
|   if (modifiers & Modifiers::kLeftButtonDown) |  | ||||||
|     modifier_strings.push_back("leftbuttondown"); |  | ||||||
|   if (modifiers & Modifiers::kMiddleButtonDown) |  | ||||||
|     modifier_strings.push_back("middlebuttondown"); |  | ||||||
|   if (modifiers & Modifiers::kRightButtonDown) |  | ||||||
|     modifier_strings.push_back("rightbuttondown"); |  | ||||||
|   if (modifiers & Modifiers::kCapsLockOn) |  | ||||||
|     modifier_strings.push_back("capslock"); |  | ||||||
|   if (modifiers & Modifiers::kNumLockOn) |  | ||||||
|     modifier_strings.push_back("numlock"); |  | ||||||
|   if (modifiers & Modifiers::kIsLeft) |  | ||||||
|     modifier_strings.push_back("left"); |  | ||||||
|   if (modifiers & Modifiers::kIsRight) |  | ||||||
|     modifier_strings.push_back("right"); |  | ||||||
|   // TODO(nornagon): the rest of the modifiers
 |  | ||||||
|   return modifier_strings; |   return modifier_strings; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -553,26 +546,11 @@ v8::Local<v8::Value> Converter<blink::WebCacheResourceTypeStats>::ToV8( | ||||||
| v8::Local<v8::Value> Converter<network::mojom::ReferrerPolicy>::ToV8( | v8::Local<v8::Value> Converter<network::mojom::ReferrerPolicy>::ToV8( | ||||||
|     v8::Isolate* isolate, |     v8::Isolate* isolate, | ||||||
|     const network::mojom::ReferrerPolicy& in) { |     const network::mojom::ReferrerPolicy& in) { | ||||||
|   switch (in) { |   for (const auto& [name, val] : ReferrerPolicies) | ||||||
|     case network::mojom::ReferrerPolicy::kDefault: |     if (val == in) | ||||||
|       return StringToV8(isolate, "default"); |       return StringToV8(isolate, name); | ||||||
|     case network::mojom::ReferrerPolicy::kAlways: | 
 | ||||||
|       return StringToV8(isolate, "unsafe-url"); |  | ||||||
|     case network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade: |  | ||||||
|       return StringToV8(isolate, "no-referrer-when-downgrade"); |  | ||||||
|     case network::mojom::ReferrerPolicy::kNever: |  | ||||||
|   return StringToV8(isolate, "no-referrer"); |   return StringToV8(isolate, "no-referrer"); | ||||||
|     case network::mojom::ReferrerPolicy::kOrigin: |  | ||||||
|       return StringToV8(isolate, "origin"); |  | ||||||
|     case network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin: |  | ||||||
|       return StringToV8(isolate, "strict-origin-when-cross-origin"); |  | ||||||
|     case network::mojom::ReferrerPolicy::kSameOrigin: |  | ||||||
|       return StringToV8(isolate, "same-origin"); |  | ||||||
|     case network::mojom::ReferrerPolicy::kStrictOrigin: |  | ||||||
|       return StringToV8(isolate, "strict-origin"); |  | ||||||
|     default: |  | ||||||
|       return StringToV8(isolate, "no-referrer"); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // static
 | // static
 | ||||||
|  | @ -580,26 +558,7 @@ bool Converter<network::mojom::ReferrerPolicy>::FromV8( | ||||||
|     v8::Isolate* isolate, |     v8::Isolate* isolate, | ||||||
|     v8::Handle<v8::Value> val, |     v8::Handle<v8::Value> val, | ||||||
|     network::mojom::ReferrerPolicy* out) { |     network::mojom::ReferrerPolicy* out) { | ||||||
|   std::string policy = base::ToLowerASCII(gin::V8ToString(isolate, val)); |   return FromV8WithLowerLookup(isolate, val, ReferrerPolicies, out); | ||||||
|   if (policy == "default") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kDefault; |  | ||||||
|   else if (policy == "unsafe-url") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kAlways; |  | ||||||
|   else if (policy == "no-referrer-when-downgrade") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade; |  | ||||||
|   else if (policy == "no-referrer") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kNever; |  | ||||||
|   else if (policy == "origin") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kOrigin; |  | ||||||
|   else if (policy == "strict-origin-when-cross-origin") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin; |  | ||||||
|   else if (policy == "same-origin") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kSameOrigin; |  | ||||||
|   else if (policy == "strict-origin") |  | ||||||
|     *out = network::mojom::ReferrerPolicy::kStrictOrigin; |  | ||||||
|   else |  | ||||||
|     return false; |  | ||||||
|   return true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // static
 | // static
 | ||||||
|  |  | ||||||
|  | @ -689,57 +689,28 @@ v8::Local<v8::Value> Converter<net::IPEndPoint>::ToV8( | ||||||
| bool Converter<net::DnsQueryType>::FromV8(v8::Isolate* isolate, | bool Converter<net::DnsQueryType>::FromV8(v8::Isolate* isolate, | ||||||
|                                           v8::Local<v8::Value> val, |                                           v8::Local<v8::Value> val, | ||||||
|                                           net::DnsQueryType* out) { |                                           net::DnsQueryType* out) { | ||||||
|   std::string query_type; |   static constexpr auto Lookup = | ||||||
|   if (!ConvertFromV8(isolate, val, &query_type)) |       base::MakeFixedFlatMapSorted<base::StringPiece, net::DnsQueryType>({ | ||||||
|     return false; |           {"A", net::DnsQueryType::A}, | ||||||
| 
 |           {"AAAA", net::DnsQueryType::AAAA}, | ||||||
|   if (query_type == "A") { |       }); | ||||||
|     *out = net::DnsQueryType::A; |   return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (query_type == "AAAA") { |  | ||||||
|     *out = net::DnsQueryType::AAAA; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return false; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // static
 | // static
 | ||||||
| bool Converter<net::HostResolverSource>::FromV8(v8::Isolate* isolate, | bool Converter<net::HostResolverSource>::FromV8(v8::Isolate* isolate, | ||||||
|                                                 v8::Local<v8::Value> val, |                                                 v8::Local<v8::Value> val, | ||||||
|                                                 net::HostResolverSource* out) { |                                                 net::HostResolverSource* out) { | ||||||
|   std::string query_type; |   using Val = net::HostResolverSource; | ||||||
|   if (!ConvertFromV8(isolate, val, &query_type)) |   static constexpr auto Lookup = | ||||||
|     return false; |       base::MakeFixedFlatMapSorted<base::StringPiece, Val>({ | ||||||
| 
 |           {"any", Val::ANY}, | ||||||
|   if (query_type == "any") { |           {"dns", Val::DNS}, | ||||||
|     *out = net::HostResolverSource::ANY; |           {"localOnly", Val::LOCAL_ONLY}, | ||||||
|     return true; |           {"mdns", Val::MULTICAST_DNS}, | ||||||
|   } |           {"system", Val::SYSTEM}, | ||||||
| 
 |       }); | ||||||
|   if (query_type == "system") { |   return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|     *out = net::HostResolverSource::SYSTEM; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (query_type == "dns") { |  | ||||||
|     *out = net::HostResolverSource::DNS; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (query_type == "mdns") { |  | ||||||
|     *out = net::HostResolverSource::MULTICAST_DNS; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (query_type == "localOnly") { |  | ||||||
|     *out = net::HostResolverSource::LOCAL_ONLY; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return false; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // static
 | // static
 | ||||||
|  | @ -747,26 +718,14 @@ bool Converter<network::mojom::ResolveHostParameters::CacheUsage>::FromV8( | ||||||
|     v8::Isolate* isolate, |     v8::Isolate* isolate, | ||||||
|     v8::Local<v8::Value> val, |     v8::Local<v8::Value> val, | ||||||
|     network::mojom::ResolveHostParameters::CacheUsage* out) { |     network::mojom::ResolveHostParameters::CacheUsage* out) { | ||||||
|   std::string query_type; |   using Val = network::mojom::ResolveHostParameters::CacheUsage; | ||||||
|   if (!ConvertFromV8(isolate, val, &query_type)) |   static constexpr auto Lookup = | ||||||
|     return false; |       base::MakeFixedFlatMapSorted<base::StringPiece, Val>({ | ||||||
| 
 |           {"allowed", Val::ALLOWED}, | ||||||
|   if (query_type == "allowed") { |           {"disallowed", Val::DISALLOWED}, | ||||||
|     *out = network::mojom::ResolveHostParameters::CacheUsage::ALLOWED; |           {"staleAllowed", Val::STALE_ALLOWED}, | ||||||
|     return true; |       }); | ||||||
|   } |   return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
| 
 |  | ||||||
|   if (query_type == "staleAllowed") { |  | ||||||
|     *out = network::mojom::ResolveHostParameters::CacheUsage::STALE_ALLOWED; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (query_type == "disallowed") { |  | ||||||
|     *out = network::mojom::ResolveHostParameters::CacheUsage::DISALLOWED; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return false; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // static
 | // static
 | ||||||
|  | @ -774,21 +733,13 @@ bool Converter<network::mojom::SecureDnsPolicy>::FromV8( | ||||||
|     v8::Isolate* isolate, |     v8::Isolate* isolate, | ||||||
|     v8::Local<v8::Value> val, |     v8::Local<v8::Value> val, | ||||||
|     network::mojom::SecureDnsPolicy* out) { |     network::mojom::SecureDnsPolicy* out) { | ||||||
|   std::string query_type; |   using Val = network::mojom::SecureDnsPolicy; | ||||||
|   if (!ConvertFromV8(isolate, val, &query_type)) |   static constexpr auto Lookup = | ||||||
|     return false; |       base::MakeFixedFlatMapSorted<base::StringPiece, Val>({ | ||||||
| 
 |           {"allow", Val::ALLOW}, | ||||||
|   if (query_type == "allow") { |           {"disable", Val::DISABLE}, | ||||||
|     *out = network::mojom::SecureDnsPolicy::ALLOW; |       }); | ||||||
|     return true; |   return FromV8WithLookup(isolate, val, Lookup, out); | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (query_type == "disable") { |  | ||||||
|     *out = network::mojom::SecureDnsPolicy::DISABLE; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return false; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // static
 | // static
 | ||||||
|  |  | ||||||
|  | @ -5,12 +5,16 @@ | ||||||
| #ifndef ELECTRON_SHELL_COMMON_GIN_CONVERTERS_STD_CONVERTER_H_ | #ifndef ELECTRON_SHELL_COMMON_GIN_CONVERTERS_STD_CONVERTER_H_ | ||||||
| #define ELECTRON_SHELL_COMMON_GIN_CONVERTERS_STD_CONVERTER_H_ | #define ELECTRON_SHELL_COMMON_GIN_CONVERTERS_STD_CONVERTER_H_ | ||||||
| 
 | 
 | ||||||
|  | #include <cstddef> | ||||||
|  | #include <functional> | ||||||
| #include <map> | #include <map> | ||||||
| #include <set> | #include <set> | ||||||
|  | #include <type_traits> | ||||||
| #include <utility> | #include <utility> | ||||||
| 
 | 
 | ||||||
| #include "gin/converter.h" | #include "gin/converter.h" | ||||||
| 
 | 
 | ||||||
|  | #include "base/strings/string_util.h" | ||||||
| #if BUILDFLAG(IS_WIN) | #if BUILDFLAG(IS_WIN) | ||||||
| #include "base/strings/string_util_win.h" | #include "base/strings/string_util_win.h" | ||||||
| #endif | #endif | ||||||
|  | @ -210,6 +214,61 @@ struct Converter<std::wstring> { | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | namespace detail { | ||||||
|  | 
 | ||||||
|  | // Get a key from `key_val` and check `lookup` for a matching entry.
 | ||||||
|  | // Return true iff a match is found, and set `*out` to the entry's value.
 | ||||||
|  | template <typename KeyType, typename Out, typename Map> | ||||||
|  | bool FromV8WithLookup(v8::Isolate* isolate, | ||||||
|  |                       v8::Local<v8::Value> key_val, | ||||||
|  |                       const Map& table, | ||||||
|  |                       Out* out, | ||||||
|  |                       std::function<void(KeyType&)> key_transform = {}) { | ||||||
|  |   static_assert(std::is_same_v<typename Map::mapped_type, Out>); | ||||||
|  | 
 | ||||||
|  |   auto key = KeyType{}; | ||||||
|  |   if (!ConvertFromV8(isolate, key_val, &key)) | ||||||
|  |     return false; | ||||||
|  | 
 | ||||||
|  |   if (key_transform) | ||||||
|  |     key_transform(key); | ||||||
|  | 
 | ||||||
|  |   if (const auto* iter = table.find(key); iter != table.end()) { | ||||||
|  |     *out = iter->second; | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | }  // namespace detail
 | ||||||
|  | 
 | ||||||
|  | // Convert `key_val to a string key and check `lookup` for a matching entry.
 | ||||||
|  | // Return true iff a match is found, and set `*out` to the entry's value.
 | ||||||
|  | template <typename Out, typename Map> | ||||||
|  | bool FromV8WithLookup(v8::Isolate* isolate, | ||||||
|  |                       v8::Local<v8::Value> key_val, | ||||||
|  |                       const Map& table, | ||||||
|  |                       Out* out) { | ||||||
|  |   return detail::FromV8WithLookup<std::string>(isolate, key_val, table, out); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Convert `key_val` to a lowercase string key and check `lookup` for a matching
 | ||||||
|  | // entry. Return true iff a match is found, and set `*out` to the entry's value.
 | ||||||
|  | template <typename Out, typename Map> | ||||||
|  | bool FromV8WithLowerLookup(v8::Isolate* isolate, | ||||||
|  |                            v8::Local<v8::Value> key_val, | ||||||
|  |                            const Map& table, | ||||||
|  |                            Out* out) { | ||||||
|  |   static constexpr auto to_lower_ascii_inplace = [](std::string& str) { | ||||||
|  |     for (auto& ch : str) | ||||||
|  |       ch = base::ToLowerASCII(ch); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return detail::FromV8WithLookup<std::string>(isolate, key_val, table, out, | ||||||
|  |                                                to_lower_ascii_inplace); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace gin
 | }  // namespace gin
 | ||||||
| 
 | 
 | ||||||
| #endif  // ELECTRON_SHELL_COMMON_GIN_CONVERTERS_STD_CONVERTER_H_
 | #endif  // ELECTRON_SHELL_COMMON_GIN_CONVERTERS_STD_CONVERTER_H_
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Charles Kerr
				Charles Kerr