Skip to content

Commit 3c73fbb

Browse files
authored
fix deleted val problem caused by move assignment to itself (#20072)
The implementation of `val& operator=(val&& v)` should not directly call `_emval_decref(handle)`. According to the semantics of move & assignment, the input argument(v) need to be reset first, and then the internal handle is judged to be a valid handle before calling `_emval_decref`. This avoids the loss of reference problem that occurs when moving the assignment to itself (this).
1 parent 91641db commit 3c73fbb

File tree

3 files changed

+17
-2
lines changed

3 files changed

+17
-2
lines changed

system/include/emscripten/val.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,12 @@ class val {
420420
}
421421

422422
val& operator=(val&& v) & {
423-
internal::_emval_decref(handle);
424-
handle = v.handle;
423+
auto v_handle = v.handle;
425424
v.handle = 0;
425+
if (handle) {
426+
internal::_emval_decref(handle);
427+
}
428+
handle = v_handle;
426429
return *this;
427430
}
428431

test/embind/test_val.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,17 @@ int main() {
225225
ensure_not(val::global("c").isArray());
226226
ensure_not(val::global("d").isArray());
227227

228+
test("val& operator=(val&& v)");
229+
val source(val::object());
230+
val target(val::object());
231+
source.set("val", 1);
232+
target = std::move(source);
233+
ensure(target["val"].as<int>() == 1);
234+
// move and assign to itself
235+
target.set("val", 2);
236+
target = std::move(target);
237+
ensure(target["val"].as<int>() == 2);
238+
228239
test("bool equals(const val& v)");
229240
EM_ASM(
230241
a = 1;

test/embind/test_val.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ test: bool isFalse()...
1515
test: bool isNumber()...
1616
test: bool isString()...
1717
test: bool isArray()...
18+
test: val& operator=(val&& v)...
1819
test: bool equals(const val& v)...
1920
test: bool operator==(const val& v)...
2021
test: bool operator!=(const val& v)...

0 commit comments

Comments
 (0)