st/theme: Reuse stylesheets if possible
The following happens when processing an `@import()` rule: 1. `_st_theme_resolve_url()` to resolve file 2. `insert_stylesheet()` to track file/sheet a. take ownership of file/sheet (ref) b. use file as key in `stylesheets_by_file` hash table c. use file as value in `files_by_stylesheet` hash table 3. release reference to file This leads to a refcount error when importing a file that was already parsed before: 1. file start with refcount 1 2. `insert_stylesheet()` a. increases refcount to 2 b. inserting into `stylesheets_by_file` *decreases* the passed-in key if the key already exists c. `files_by_stylesheet` now tracks a file with recount 1 3. releases the last reference to file The file object tracked in `files_by_stylesheet` is now invalid, and accessing it results in a crash. Avoid this issue by reusing existing stylesheets, so we don't insert a stylesheet that's already tracked. As a side-effect, this also saves us from re-parsing the same file unnecessarily. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7306 Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3619>
This commit is contained in:
parent
e5b81e19f5
commit
829d2fd469
@ -244,6 +244,27 @@ insert_stylesheet (StTheme *theme,
|
|||||||
g_hash_table_insert (theme->files_by_stylesheet, stylesheet, file);
|
g_hash_table_insert (theme->files_by_stylesheet, stylesheet, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CRStyleSheet *
|
||||||
|
resolve_stylesheet (StTheme *theme,
|
||||||
|
GFile *file,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
CRStyleSheet *sheet;
|
||||||
|
|
||||||
|
sheet = g_hash_table_lookup (theme->stylesheets_by_file, file);
|
||||||
|
if (sheet)
|
||||||
|
{
|
||||||
|
cr_stylesheet_ref (sheet);
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
sheet = parse_stylesheet (file, error);
|
||||||
|
if (sheet)
|
||||||
|
insert_stylesheet (theme, file, sheet);
|
||||||
|
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* st_theme_load_stylesheet:
|
* st_theme_load_stylesheet:
|
||||||
* @theme: a #StTheme
|
* @theme: a #StTheme
|
||||||
@ -261,13 +282,12 @@ st_theme_load_stylesheet (StTheme *theme,
|
|||||||
{
|
{
|
||||||
CRStyleSheet *stylesheet;
|
CRStyleSheet *stylesheet;
|
||||||
|
|
||||||
stylesheet = parse_stylesheet (file, error);
|
stylesheet = resolve_stylesheet (theme, file, error);
|
||||||
if (!stylesheet)
|
if (!stylesheet)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
stylesheet->app_data = GUINT_TO_POINTER (TRUE);
|
stylesheet->app_data = GUINT_TO_POINTER (TRUE);
|
||||||
|
|
||||||
insert_stylesheet (theme, file, stylesheet);
|
|
||||||
cr_stylesheet_ref (stylesheet);
|
cr_stylesheet_ref (stylesheet);
|
||||||
theme->custom_stylesheets = g_slist_prepend (theme->custom_stylesheets, stylesheet);
|
theme->custom_stylesheets = g_slist_prepend (theme->custom_stylesheets, stylesheet);
|
||||||
g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0);
|
g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0);
|
||||||
@ -884,6 +904,7 @@ add_matched_properties (StTheme *a_this,
|
|||||||
|
|
||||||
if (import_rule->sheet == NULL)
|
if (import_rule->sheet == NULL)
|
||||||
{
|
{
|
||||||
|
CRStyleSheet *sheet = NULL;
|
||||||
GFile *file = NULL;
|
GFile *file = NULL;
|
||||||
|
|
||||||
if (import_rule->url->stryng && import_rule->url->stryng->str)
|
if (import_rule->url->stryng && import_rule->url->stryng->str)
|
||||||
@ -891,13 +912,12 @@ add_matched_properties (StTheme *a_this,
|
|||||||
file = _st_theme_resolve_url (a_this,
|
file = _st_theme_resolve_url (a_this,
|
||||||
a_nodesheet,
|
a_nodesheet,
|
||||||
import_rule->url->stryng->str);
|
import_rule->url->stryng->str);
|
||||||
import_rule->sheet = parse_stylesheet (file, NULL);
|
sheet = resolve_stylesheet (a_this, file, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import_rule->sheet)
|
if (sheet)
|
||||||
{
|
{
|
||||||
insert_stylesheet (a_this, file, import_rule->sheet);
|
import_rule->sheet = sheet;
|
||||||
/* refcount of stylesheets starts off at zero, so we don't need to unref! */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user