Repository: electron/electron
Pull request: perf: prefer NewFromUtf8Literal() over NewFromUtf8() for string literals

#### Description of Change

`NewFromUtf8Literal()` passes in the literal's string length at compile time and avoids the need to call `.ToLocalChecked()`.

#### Checklist

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: none.

Changed files:
filename: shell/common/api/electron_api_asar.cc
patch: @@ -18,8 +18,7 @@ class Archive : public node::ObjectWrap {
   static v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
       v8::Isolate* isolate) {
     auto tpl = v8::FunctionTemplate::New(isolate, Archive::New);
-    tpl->SetClassName(
-        v8::String::NewFromUtf8(isolate, "Archive").ToLocalChecked());
+    tpl->SetClassName(v8::String::NewFromUtf8Literal(isolate, "Archive"));
     tpl->InstanceTemplate()->SetInternalFieldCount(1);
 
     NODE_SET_PROTOTYPE_METHOD(tpl, "getFileInfo", &Archive::GetFileInfo);

filename: shell/renderer/api/electron_api_web_frame.cc
patch: @@ -146,7 +146,7 @@ class ScriptExecutionCallback {
       const v8::Local<v8::Object>& result) {
     v8::MaybeLocal<v8::Value> maybe_result;
     bool success = true;
-    std::string error_message =
+    std::string errmsg =
         "An unknown exception occurred while getting the result of the script";
     {
       v8::TryCatch try_catch(isolate);
@@ -164,7 +164,7 @@ class ScriptExecutionCallback {
         auto message = try_catch.Message();
 
         if (!message.IsEmpty()) {
-          gin::ConvertFromV8(isolate, message->Get(), &error_message);
+          gin::ConvertFromV8(isolate, message->Get(), &errmsg);
         }
       }
     }
@@ -173,10 +173,11 @@ class ScriptExecutionCallback {
       if (callback_)
         std::move(callback_).Run(
             v8::Undefined(isolate),
-            v8::Exception::Error(
-                v8::String::NewFromUtf8(isolate, error_message.c_str())
-                    .ToLocalChecked()));
-      promise_.RejectWithErrorMessage(error_message);
+            v8::Exception::Error(v8::String::NewFromUtf8(
+                                     isolate, errmsg.data(),
+                                     v8::NewStringType::kNormal, errmsg.size())
+                                     .ToLocalChecked()));
+      promise_.RejectWithErrorMessage(errmsg);
     } else {
       v8::Local<v8::Context> context = promise_.GetContext();
       v8::Context::Scope context_scope(context);
@@ -210,7 +211,7 @@ class ScriptExecutionCallback {
           promise_.Resolve(value);
         }
       } else {
-        const char error_message[] =
+        const char errmsg[] =
             "Script failed to execute, this normally means an error "
             "was thrown. Check the renderer console for the error.";
         if (!callback_.is_null()) {
@@ -219,24 +220,23 @@ class ScriptExecutionCallback {
           std::move(callback_).Run(
               v8::Undefined(isolate),
               v8::Exception::Error(
-                  v8::String::NewFromUtf8(isolate, error_message)
-                      .ToLocalChecked()));
+                  v8::String::NewFromUtf8Literal(isolate, errmsg)));
         }
-        promise_.RejectWithErrorMessage(error_message);
+        promise_.RejectWithErrorMessage(errmsg);
       }
     } else {
-      const char error_message[] =
+      const char errmsg[] =
           "WebFrame was removed before script could run. This normally means "
           "the underlying frame was destroyed";
       if (!callback_.is_null()) {
         v8::Local<v8::Context> context = promise_.GetContext();
         v8::Context::Scope context_scope(context);
         std::move(callback_).Run(
             v8::Undefined(isolate),
-            v8::Exception::Error(v8::String::NewFromUtf8(isolate, error_message)
-                                     .ToLocalChecked()));
+            v8::Exception::Error(
+                v8::String::NewFromUtf8Literal(isolate, errmsg)));
       }
-      promise_.RejectWithErrorMessage(error_message);
+      promise_.RejectWithErrorMessage(errmsg);
     }
     delete this;
   }
@@ -716,15 +716,14 @@ class WebFrameRenderer final : public gin::Wrappable<WebFrameRenderer>,
       script.Get("url", &url);
 
       if (!script.Get("code", &code)) {
-        const char error_message[] = "Invalid 'code'";
+        const char errmsg[] = "Invalid 'code'";
         if (!completion_callback.is_null()) {
           std::move(completion_callback)
               .Run(v8::Undefined(isolate),
                    v8::Exception::Error(
-                       v8::String::NewFromUtf8(isolate, error_message)
-                           .ToLocalChecked()));
+                       v8::String::NewFromUtf8Literal(isolate, errmsg)));
         }
-        promise.RejectWithErrorMessage(error_message);
+        promise.RejectWithErrorMessage(errmsg);
         return handle;
       }
 

filename: shell/renderer/electron_renderer_client.cc
patch: @@ -122,11 +122,11 @@ void ElectronRendererClient::DidCreateScriptContext(
                                    "Headers"};
   for (const auto& key : keys) {
     v8::MaybeLocal<v8::Value> value =
-        global->Get(renderer_context, gin::StringToV8(isolate, key.c_str()));
+        global->Get(renderer_context, gin::StringToV8(isolate, key));
     if (!value.IsEmpty()) {
       std::string blink_key = "blink" + key;
       global
-          ->Set(renderer_context, gin::StringToV8(isolate, blink_key.c_str()),
+          ->Set(renderer_context, gin::StringToV8(isolate, blink_key),
                 value.ToLocalChecked())
           .Check();
     }

filename: shell/renderer/electron_sandboxed_renderer_client.cc
patch: @@ -57,7 +57,7 @@ v8::Local<v8::Value> GetBinding(v8::Isolate* isolate,
   std::string binding_key = gin::V8ToString(isolate, key);
   gin_helper::Dictionary cache(isolate, GetBindingCache(isolate));
 
-  if (cache.Get(binding_key.c_str(), &exports)) {
+  if (cache.Get(binding_key, &exports)) {
     return exports;
   }
 
@@ -76,7 +76,7 @@ v8::Local<v8::Value> GetBinding(v8::Isolate* isolate,
   DCHECK_NE(mod->nm_context_register_func, nullptr);
   mod->nm_context_register_func(exports, v8::Null(isolate),
                                 isolate->GetCurrentContext(), mod->nm_priv);
-  cache.Set(binding_key.c_str(), exports);
+  cache.Set(binding_key, exports);
   return exports;
 }