Skip to content

Commit e0b76b9

Browse files
authored
fix: external memory usage adjustment mismatch (#1123)
1 parent 2713af6 commit e0b76b9

File tree

4 files changed

+39
-11
lines changed

4 files changed

+39
-11
lines changed

.github/workflows/CI.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ jobs:
288288
target: 'aarch64-apple-darwin'
289289
- host: windows-latest
290290
target: 'x86_64-pc-windows-msvc'
291-
node: ['20', '22']
291+
node: ['20', '22', '24']
292292
runs-on: ${{ matrix.settings.host }}
293293

294294
steps:
@@ -351,7 +351,7 @@ jobs:
351351
strategy:
352352
fail-fast: false
353353
matrix:
354-
node: ['18', '20', '22']
354+
node: ['20', '22', '24']
355355
runs-on: ubuntu-latest
356356

357357
steps:
@@ -402,7 +402,7 @@ jobs:
402402
strategy:
403403
fail-fast: false
404404
matrix:
405-
node: ['20', '22']
405+
node: ['20', '22', '24']
406406
runs-on: ubuntu-latest
407407

408408
steps:
@@ -455,7 +455,7 @@ jobs:
455455
strategy:
456456
fail-fast: false
457457
matrix:
458-
node: ['20', '22']
458+
node: ['20', '22', '24']
459459
runs-on: ubuntu-24.04-arm
460460

461461
steps:

src/ctx.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,7 @@ impl CanvasRenderingContext2D {
16861686
#[napi]
16871687
pub fn draw_image(
16881688
&mut self,
1689+
env: &Env,
16891690
image: Either3<&mut CanvasElement, &mut SVGCanvas, &mut Image>,
16901691
sx: Option<f64>,
16911692
sy: Option<f64>,
@@ -1703,7 +1704,7 @@ impl CanvasRenderingContext2D {
17031704
if !image.complete {
17041705
return Ok(());
17051706
}
1706-
image.regenerate_bitmap_if_need()?;
1707+
image.regenerate_bitmap_if_need(env)?;
17071708
if let Some(bitmap) = &mut image.bitmap {
17081709
BitmapRef::Borrowed(bitmap)
17091710
} else {

src/image.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,14 @@ pub struct Image {
120120
file_content: Option<Vec<u8>>,
121121
// take ownership of avif image, let it be dropped when image is dropped
122122
_avif_image_ref: Option<AvifImage>,
123+
// Bytes accounted to V8 via adjust_external_memory for this image
124+
accounted_bytes: i64,
123125
}
124126

125127
impl ObjectFinalize for Image {
126128
fn finalize(self, env: Env) -> Result<()> {
127-
if let Some(bitmap) = self.bitmap {
128-
env.adjust_external_memory(-(bitmap.0.width as i64) * (bitmap.0.height as i64) * 4)?;
129+
if self.accounted_bytes != 0 {
130+
env.adjust_external_memory(-self.accounted_bytes)?;
129131
}
130132
Ok(())
131133
}
@@ -152,6 +154,7 @@ impl Image {
152154
src: None,
153155
file_content: None,
154156
_avif_image_ref: None,
157+
accounted_bytes: 0,
155158
})
156159
}
157160

@@ -266,7 +269,7 @@ impl Image {
266269
Ok(())
267270
}
268271

269-
pub(crate) fn regenerate_bitmap_if_need(&mut self) -> Result<()> {
272+
pub(crate) fn regenerate_bitmap_if_need(&mut self, env: &Env) -> Result<()> {
270273
if !self.need_regenerate_bitmap || !self.is_svg || self.src.is_none() {
271274
return Ok(());
272275
}
@@ -281,6 +284,11 @@ impl Image {
281284
self.color_space,
282285
&font,
283286
);
287+
if let Some(bmp) = &self.bitmap {
288+
let new_bytes = (bmp.0.width as i64) * (bmp.0.height as i64) * 4;
289+
self.adjust_external_memory_if_need(env, new_bytes)?;
290+
}
291+
self.need_regenerate_bitmap = false;
284292
return Ok(());
285293
}
286294
if let Some(data) = self.src.as_ref() {
@@ -293,6 +301,20 @@ impl Image {
293301
self.color_space,
294302
&font,
295303
);
304+
if let Some(bmp) = &self.bitmap {
305+
let new_bytes = (bmp.0.width as i64) * (bmp.0.height as i64) * 4;
306+
self.adjust_external_memory_if_need(env, new_bytes)?;
307+
}
308+
self.need_regenerate_bitmap = false;
309+
}
310+
Ok(())
311+
}
312+
313+
fn adjust_external_memory_if_need(&mut self, env: &Env, new_bytes: i64) -> Result<()> {
314+
let delta = new_bytes - self.accounted_bytes;
315+
if delta != 0 {
316+
env.adjust_external_memory(delta)?;
317+
self.accounted_bytes = new_bytes;
296318
}
297319
Ok(())
298320
}
@@ -518,7 +540,12 @@ impl Task for BitmapDecoder {
518540
self_mut.is_svg = bitmap.is_svg;
519541
self_mut.bitmap = Some(bitmap.data);
520542
self_mut._avif_image_ref = bitmap.decoded_image;
521-
env.adjust_external_memory((output.width as i64) * (output.height as i64) * 4)?;
543+
let new_bytes = (output.width as i64) * (output.height as i64) * 4;
544+
let delta = new_bytes - self_mut.accounted_bytes;
545+
if delta != 0 {
546+
env.adjust_external_memory(delta)?;
547+
self_mut.accounted_bytes = new_bytes;
548+
}
522549
}
523550
DecodeStatus::Empty => {}
524551
DecodeStatus::InvalidSvg => {

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl<'c> CanvasElement<'c> {
144144
&mut self.ctx.context,
145145
Context::new(width, height, ColorSpace::default())?,
146146
);
147-
env.adjust_external_memory((width as i64 - old_ctx.width as i64) * 4)?;
147+
env.adjust_external_memory((width as i64 - old_ctx.width as i64) * (height as i64) * 4)?;
148148
Ok(())
149149
}
150150

@@ -162,7 +162,7 @@ impl<'c> CanvasElement<'c> {
162162
&mut self.ctx.context,
163163
Context::new(width, height, ColorSpace::default())?,
164164
);
165-
env.adjust_external_memory((height as i64 - old_ctx.height as i64) * 4)?;
165+
env.adjust_external_memory((height as i64 - old_ctx.height as i64) * (width as i64) * 4)?;
166166
Ok(())
167167
}
168168

0 commit comments

Comments
 (0)