From 8ea50a77fd14752aba5d1e706fdd24866e382c2d Mon Sep 17 00:00:00 2001 From: happy-capybara-man Date: Thu, 18 Dec 2025 01:39:27 +0800 Subject: [PATCH] js: restore deep copy behavior for Mat.clone() Emscripten 3.1.71+ introduced ClassHandle.clone() which performs a shallow copy. This shadowed the original OpenCV clone() method which was intended for deep copying. This patch: 1. Hooks into onRuntimeInitialized in helpers.js 2. Overrides cv.Mat.prototype.clone to point to mat_clone (deep copy) 3. Updates JS tests to use clone() to verify the fix --- modules/js/src/helpers.js | 17 +++++++++++++++++ modules/js/test/test_mat.js | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/modules/js/src/helpers.js b/modules/js/src/helpers.js index ab88d18eec..67dc8639fa 100644 --- a/modules/js/src/helpers.js +++ b/modules/js/src/helpers.js @@ -410,3 +410,20 @@ if ( if (cv.UMat) cv.UMat.prototype[Symbol.dispose] = cv.UMat.prototype.delete; // Add more as OpenCV gains new manual-cleanup classes } + +// Override Emscripten's shallow clone() with OpenCV's deep copy mat_clone() +// This restores the expected behavior where clone() performs a deep copy. +// Background: Emscripten 3.1.71+ added ClassHandle.clone() which only does shallow copy. +// See: https://github.com/opencv/opencv/pull/26643 +// See: https://github.com/opencv/opencv/issues/27572 +var _opencv_onRuntimeInitialized_backup = Module['onRuntimeInitialized']; +Module['onRuntimeInitialized'] = function() { + if (_opencv_onRuntimeInitialized_backup) { + _opencv_onRuntimeInitialized_backup(); + } + if (typeof cv !== 'undefined' && cv.Mat && + typeof cv.Mat.prototype.mat_clone === 'function') { + cv.Mat.prototype.clone = cv.Mat.prototype.mat_clone; + } +}; + diff --git a/modules/js/test/test_mat.js b/modules/js/test/test_mat.js index f0c5211568..a1d5c98b17 100644 --- a/modules/js/test/test_mat.js +++ b/modules/js/test/test_mat.js @@ -173,7 +173,7 @@ QUnit.test('test_mat_creation', function(assert) { // clone { let mat = cv.Mat.ones(5, 5, cv.CV_8UC1); - let mat2 = mat.mat_clone(); + let mat2 = mat.clone(); assert.equal(mat.channels, mat2.channels); assert.equal(mat.size().height, mat2.size().height);