Compare commits

...

2 Commits

Author SHA1 Message Date
Charles Kerr
ae9577a9fc perf: use v8::String::NewFromUtf8Literal() in gin_helper::Dictionary 2024-08-02 09:29:52 -05:00
Charles Kerr
49dcea330a perf: use v8::String::NewFromUtf8Literal() for literals
A little more efficient than using gin converters or NewFromUtf8():
since the string info is known at compile time, NewFromUtf8Literal()
skips the runtime checks.
2024-08-02 09:29:52 -05:00
16 changed files with 77 additions and 48 deletions

View File

@@ -39,7 +39,7 @@ void AutoUpdater::OnError(const std::string& message) {
if (GetWrapper(isolate).ToLocal(&wrapper)) {
auto error = v8::Exception::Error(gin::StringToV8(isolate, message));
std::vector<v8::Local<v8::Value>> args = {
gin::StringToV8(isolate, "error"),
v8::String::NewFromUtf8Literal(isolate, "error"),
gin::ConvertToV8(
isolate,
error->ToObject(isolate->GetCurrentContext()).ToLocalChecked()),
@@ -70,11 +70,11 @@ void AutoUpdater::OnError(const std::string& message,
// add two new params for better error handling
errorObject
->Set(context, gin::StringToV8(isolate, "code"),
->Set(context, v8::String::NewFromUtf8Literal(isolate, "code"),
v8::Integer::New(isolate, code))
.Check();
errorObject
->Set(context, gin::StringToV8(isolate, "domain"),
->Set(context, v8::String::NewFromUtf8Literal(isolate, "domain"),
gin::StringToV8(isolate, domain))
.Check();

View File

@@ -722,8 +722,8 @@ void BaseWindow::SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> value) {
} else if (value->IsNull()) {
RemoveMenu();
} else {
isolate->ThrowException(
v8::Exception::TypeError(gin::StringToV8(isolate, "Invalid Menu")));
isolate->ThrowException(v8::Exception::TypeError(
v8::String::NewFromUtf8Literal(isolate, "Invalid Menu")));
}
}
@@ -1144,7 +1144,8 @@ gin_helper::WrappableBase* BaseWindow::New(gin_helper::Arguments* args) {
// static
void BaseWindow::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "BaseWindow"));
prototype->SetClassName(
v8::String::NewFromUtf8Literal(isolate, "BaseWindow"));
gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("setContentView", &BaseWindow::SetContentView)

View File

@@ -346,7 +346,8 @@ gin_helper::WrappableBase* BrowserWindow::New(gin_helper::ErrorThrower thrower,
// static
void BrowserWindow::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "BrowserWindow"));
prototype->SetClassName(
v8::String::NewFromUtf8Literal(isolate, "BrowserWindow"));
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("focusOnWebView", &BrowserWindow::FocusOnWebView)
.SetMethod("blurWebView", &BrowserWindow::BlurWebView)

View File

@@ -79,17 +79,17 @@ struct Converter<net::CookieChangeCause> {
switch (val) {
case net::CookieChangeCause::INSERTED:
case net::CookieChangeCause::EXPLICIT:
return gin::StringToV8(isolate, "explicit");
return v8::String::NewFromUtf8Literal(isolate, "explicit");
case net::CookieChangeCause::OVERWRITE:
return gin::StringToV8(isolate, "overwrite");
return v8::String::NewFromUtf8Literal(isolate, "overwrite");
case net::CookieChangeCause::EXPIRED:
return gin::StringToV8(isolate, "expired");
return v8::String::NewFromUtf8Literal(isolate, "expired");
case net::CookieChangeCause::EVICTED:
return gin::StringToV8(isolate, "evicted");
return v8::String::NewFromUtf8Literal(isolate, "evicted");
case net::CookieChangeCause::EXPIRED_OVERWRITE:
return gin::StringToV8(isolate, "expired-overwrite");
return v8::String::NewFromUtf8Literal(isolate, "expired-overwrite");
default:
return gin::StringToV8(isolate, "unknown");
return v8::String::NewFromUtf8Literal(isolate, "unknown");
}
}
};

View File

@@ -338,10 +338,10 @@ class ClearDataTask {
// Create a rich error object with extra detail about what data types
// failed
auto error = v8::Exception::Error(
gin::StringToV8(isolate, "Failed to clear data"));
v8::String::NewFromUtf8Literal(isolate, "Failed to clear data"));
error.As<v8::Object>()
->Set(promise_.GetContext(),
gin::StringToV8(isolate, "failedDataTypes"),
v8::String::NewFromUtf8Literal(isolate, "failedDataTypes"),
failed_data_types_array)
.Check();
@@ -1046,13 +1046,15 @@ void Session::CreateInterruptedDownload(const gin_helper::Dictionary& options) {
options.Get("eTag", &etag);
options.Get("startTime", &start_time);
if (path.empty() || url_chain.empty() || length == 0) {
isolate_->ThrowException(v8::Exception::Error(gin::StringToV8(
isolate_, "Must pass non-empty path, urlChain and length.")));
isolate_->ThrowException(
v8::Exception::Error(v8::String::NewFromUtf8Literal(
isolate_, "Must pass non-empty path, urlChain and length.")));
return;
}
if (offset >= length) {
isolate_->ThrowException(v8::Exception::Error(gin::StringToV8(
isolate_, "Must pass an offset value less than length.")));
isolate_->ThrowException(
v8::Exception::Error(v8::String::NewFromUtf8Literal(
isolate_, "Must pass an offset value less than length.")));
return;
}
auto* download_manager = browser_context()->GetDownloadManager();

View File

@@ -208,7 +208,7 @@ int SystemPreferences::DoSubscribeNotification(
if (!(maybe_name->IsNull() ||
gin::ConvertFromV8(isolate, maybe_name, &name_str))) {
isolate->ThrowException(v8::Exception::Error(
gin::StringToV8(isolate, "Must pass null or a string")));
v8::String::NewFromUtf8Literal(isolate, "Must pass null or a string")));
return -1;
}

View File

@@ -420,7 +420,7 @@ gin::Handle<View> View::Create(v8::Isolate* isolate) {
// static
void View::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "View"));
prototype->SetClassName(v8::String::NewFromUtf8Literal(isolate, "View"));
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("addChildView", &View::AddChildViewAt)
.SetMethod("removeChildView", &View::RemoveChildView)

View File

@@ -3384,8 +3384,8 @@ void WebContents::SendInputEvent(v8::Isolate* isolate,
}
}
isolate->ThrowException(
v8::Exception::Error(gin::StringToV8(isolate, "Invalid event object")));
isolate->ThrowException(v8::Exception::Error(
v8::String::NewFromUtf8Literal(isolate, "Invalid event object")));
}
void WebContents::BeginFrameSubscription(gin::Arguments* args) {

View File

@@ -226,7 +226,8 @@ gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) {
void WebContentsView::BuildPrototype(
v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "WebContentsView"));
prototype->SetClassName(
v8::String::NewFromUtf8Literal(isolate, "WebContentsView"));
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("setBackgroundColor", &WebContentsView::SetBackgroundColor)
.SetMethod("setBorderRadius", &WebContentsView::SetBorderRadius)

View File

@@ -187,8 +187,8 @@ void WebFrameMain::Send(v8::Isolate* isolate,
v8::Local<v8::Value> args) {
blink::CloneableMessage message;
if (!gin::ConvertFromV8(isolate, args, &message)) {
isolate->ThrowException(v8::Exception::Error(
gin::StringToV8(isolate, "Failed to serialize arguments")));
isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8Literal(
isolate, "Failed to serialize arguments")));
return;
}
@@ -251,8 +251,9 @@ void WebFrameMain::PostMessage(v8::Isolate* isolate,
std::vector<gin::Handle<MessagePort>> wrapped_ports;
if (transfer && !transfer.value()->IsUndefined()) {
if (!gin::ConvertFromV8(isolate, *transfer, &wrapped_ports)) {
isolate->ThrowException(v8::Exception::Error(
gin::StringToV8(isolate, "Invalid value for transfer")));
isolate->ThrowException(
v8::Exception::Error(v8::String::NewFromUtf8Literal(
isolate, "Invalid value for transfer")));
return;
}
}

View File

@@ -34,7 +34,7 @@ gin_helper::WrappableBase* ImageView::New(gin_helper::Arguments* args) {
// static
void ImageView::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "ImageView"));
prototype->SetClassName(v8::String::NewFromUtf8Literal(isolate, "ImageView"));
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("setImage", &ImageView::SetImage);
}

View File

@@ -26,11 +26,11 @@ struct Converter<electron::BundlerMoverConflictType> {
electron::BundlerMoverConflictType value) {
switch (value) {
case electron::BundlerMoverConflictType::kExists:
return gin::StringToV8(isolate, "exists");
return v8::String::NewFromUtf8Literal(isolate, "exists");
case electron::BundlerMoverConflictType::kExistsAndRunning:
return gin::StringToV8(isolate, "existsAndRunning");
return v8::String::NewFromUtf8Literal(isolate, "existsAndRunning");
default:
return gin::StringToV8(isolate, "");
return v8::String::NewFromUtf8Literal(isolate, "");
}
}
};

View File

@@ -143,7 +143,7 @@ v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
v8::Local<v8::Value> arg1,
v8::Local<v8::Value> arg2) {
v8::MaybeLocal<v8::Value> bind =
func->Get(context, gin::StringToV8(isolate, "bind"));
func->Get(context, v8::String::NewFromUtf8Literal(isolate, "bind"));
CHECK(!bind.IsEmpty());
v8::Local<v8::Function> bind_func = bind.ToLocalChecked().As<v8::Function>();
v8::Local<v8::Value> converted[] = {func, arg1, arg2};

View File

@@ -38,14 +38,12 @@ class Dictionary : public gin::Dictionary {
// Differences from the Get method in gin::Dictionary:
// 1. This is a const method;
// 2. It checks whether the key exists before reading;
// 3. It accepts arbitrary type of key.
template <typename K, typename V>
bool Get(const K& key, V* out) const {
// 2. It checks whether the key exists before reading
template <typename V>
bool Get(v8::Local<v8::Value> v8_key, V* out) const {
v8::Isolate* const iso = isolate();
v8::Local<v8::Object> handle = GetHandle();
v8::Local<v8::Context> context = iso->GetCurrentContext();
v8::Local<v8::Value> v8_key = gin::ConvertToV8(iso, key);
v8::Local<v8::Value> value;
// Check for existence before getting, otherwise this method will always
// returns true when T == v8::Local<v8::Value>.
@@ -54,17 +52,39 @@ class Dictionary : public gin::Dictionary {
gin::ConvertFromV8(iso, value, out);
}
// Get() variant optimized for string literals e.g. `Get("key", &val)`
template <int N, typename V>
bool Get(const char (&key_literal)[N], V* out) const {
return Get(v8::String::NewFromUtf8Literal(isolate(), key_literal), out);
}
// Get() variant that accepts arbitrary key types
template <typename K, typename V>
bool Get(const K& key, V* out) const {
return Get(gin::ConvertToV8(isolate(), key), out);
}
// Differences from the Set method in gin::Dictionary:
// 1. It accepts arbitrary type of key.
template <typename K, typename V>
bool Set(const K& key, const V& val) {
bool Set(v8::Local<v8::Value> v8_key, const V& value) {
v8::Local<v8::Value> v8_value;
if (!gin::TryConvertToV8(isolate(), val, &v8_value))
return false;
v8::Maybe<bool> result =
GetHandle()->Set(isolate()->GetCurrentContext(),
gin::ConvertToV8(isolate(), key), v8_value);
return result.FromMaybe(false);
return gin::TryConvertToV8(isolate(), value, &v8_value) &&
GetHandle()
->Set(isolate()->GetCurrentContext(), v8_key, v8_value)
.FromMaybe(false);
}
// Set() variant optimized for string literals e.g. `Set("key", val)`
template <int N, typename V>
bool Set(const char (&key_literal)[N], const V& val) {
return Set(v8::String::NewFromUtf8Literal(isolate(), key_literal), val);
}
// Set() variant that accepts abitrary key types
template <typename K, typename V>
bool Set(const K& key, const V& val) {
return Set(gin::ConvertToV8(isolate(), key), val);
}
// Like normal Get but put result in an std::optional.

View File

@@ -43,8 +43,9 @@ class V8Serializer : public v8::ValueSerializer::Delegate {
bool wrote_value;
if (!serializer_.WriteValue(isolate_->GetCurrentContext(), value)
.To(&wrote_value)) {
isolate_->ThrowException(v8::Exception::Error(
gin::StringToV8(isolate_, "An object could not be cloned.")));
isolate_->ThrowException(
v8::Exception::Error(v8::String::NewFromUtf8Literal(
isolate_, "An object could not be cloned.")));
return false;
}
DCHECK(wrote_value);

View File

@@ -539,7 +539,9 @@ class WebFrameRenderer : public gin::Wrappable<WebFrameRenderer>,
const std::string& language,
v8::Local<v8::Object> provider) {
auto context = isolate->GetCurrentContext();
if (!provider->Has(context, gin::StringToV8(isolate, "spellCheck"))
if (!provider
->Has(context,
v8::String::NewFromUtf8Literal(isolate, "spellCheck"))
.ToChecked()) {
thrower.ThrowError("\"spellCheck\" has to be defined");
return;