WebIDL - JsString variants for performance for `CanvasRenderingContext2d::set_fill_style()`

Author: ThomasHabetsCreated Jul 7, 2026Updated Aug 7, 2026
Labelsfrontend:webidl

set_fill_style is deprecated. Looks like it was deprecated in 95bf437f35eaef8ee0756dba8685b2ff2278536c, when the _str and _gradient were added.

_str() is right out, for me. Turning &str into JsValue for set_fill_style_str() is about 50% of my UI thread.

I tried to create a gradient instead, and cache that, but that caused main UI thread CPU time to just explode.

Draw using

  • set_fill_style(): about 35ms to draw.
  • set_fill_style_str(): About 73ms.
  • set_fill_style_canvas_gradient(): 536ms(!). That is a showstopper, especially in the UI thread.

For _str() the time goes to converting to JsValue, whereas for _canvas_gradient() it's just an enormous __wbg_fillRect / fillRect.

This is my use of set_fill_style(). The gradient version is not checked in, but similar. Key part:

rust
     COLOR_CACHE.with(|slot| {
         slot.borrow_mut()
-            .entry(s.to_owned())
-            .or_insert_with(|| JsValue::from_str(s))
+            .entry(s)
+            .or_insert_with(move || {
+                let gradient = ctx.create_linear_gradient(0.0, 0.0, 1.0, 0.0);
+                let (r, g, b) = s;
+                let color = format!("rgb({r},{g},{b})");
+
+                gradient.add_color_stop(0.0, &color).unwrap();
+                gradient.add_color_stop(1.0, &color).unwrap();
+                gradient
+            })
             .clone()
     })

Are the non-deprecated functions really suitable replacements, or is there something I'm missing?

I saw it was linked to https://github.com/rustwasm/wasm-bindgen/pull/4156, and do I understand that this could be because one can only update these from the UI thread, not using shared buffers? Well, I'm doing it from the UI thread.

Source: wasm-bindgen/wasm-bindgen