Skip to content

Commit 3052664

Browse files
authored
[embind] Fix return value policy for constructors. (#21981)
Use the `take_ownership` policy by default for constructors. This handles the case where an external constructor returns by value and has no copy constructor. This seems to be a sane default, since a constructor binding should imply that JS is taking ownership when it's called.
1 parent 91b348d commit 3052664

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

system/include/emscripten/bind.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ struct RegisterClassConstructor<ReturnType (*)(Args...)> {
13881388
template <typename ClassType, typename... Policies>
13891389
static void invoke(ReturnType (*factory)(Args...)) {
13901390
typename WithPolicies<allow_raw_pointers, Policies...>::template ArgTypeList<ReturnType, Args...> args;
1391-
using ReturnPolicy = rvp::default_tag;
1391+
using ReturnPolicy = rvp::take_ownership;
13921392
auto invoke = &Invoker<ReturnPolicy, ReturnType, Args...>::invoke;
13931393
_embind_register_class_constructor(
13941394
TypeID<ClassType>::get(),
@@ -1406,7 +1406,7 @@ struct RegisterClassConstructor<std::function<ReturnType (Args...)>> {
14061406
template <typename ClassType, typename... Policies>
14071407
static void invoke(std::function<ReturnType (Args...)> factory) {
14081408
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args;
1409-
using ReturnPolicy = rvp::default_tag;
1409+
using ReturnPolicy = rvp::take_ownership;
14101410
auto invoke = &FunctorInvoker<ReturnPolicy, decltype(factory), ReturnType, Args...>::invoke;
14111411
_embind_register_class_constructor(
14121412
TypeID<ClassType>::get(),
@@ -1423,7 +1423,7 @@ struct RegisterClassConstructor<ReturnType (Args...)> {
14231423
template <typename ClassType, typename Callable, typename... Policies>
14241424
static void invoke(Callable& factory) {
14251425
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args;
1426-
using ReturnPolicy = rvp::default_tag;
1426+
using ReturnPolicy = rvp::take_ownership;
14271427
auto invoke = &FunctorInvoker<ReturnPolicy, decltype(factory), ReturnType, Args...>::invoke;
14281428
_embind_register_class_constructor(
14291429
TypeID<ClassType>::get(),

test/embind/embind.test.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,6 +1827,13 @@ module({
18271827
assert.equal("foo", e.getString());
18281828
e.delete();
18291829
});
1830+
1831+
test("can construct class with external constructor with no copy constructor", function() {
1832+
var e = new cm.HasExternalConstructorNoCopy(42);
1833+
assert.instanceof(e, cm.HasExternalConstructorNoCopy);
1834+
assert.equal(42, e.getInt());
1835+
e.delete();
1836+
});
18301837
});
18311838

18321839
BaseFixture.extend("const", function() {

test/embind/embind_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,22 @@ HasExternalConstructor* createHasExternalConstructor(const std::string& str) {
16091609
return new HasExternalConstructor(str);
16101610
}
16111611

1612+
class HasExternalConstructorNoCopy {
1613+
private:
1614+
HasExternalConstructorNoCopy(int i) : m(i) {}
1615+
int m;
1616+
public:
1617+
HasExternalConstructorNoCopy(HasExternalConstructorNoCopy&) = delete;
1618+
HasExternalConstructorNoCopy(HasExternalConstructorNoCopy&&) = default;
1619+
int getInt() {
1620+
return m;
1621+
}
1622+
static HasExternalConstructorNoCopy create(int i) {
1623+
HasExternalConstructorNoCopy obj(i);
1624+
return obj;
1625+
}
1626+
};
1627+
16121628
template<typename T>
16131629
class CustomSmartPtr {
16141630
public:
@@ -2411,6 +2427,11 @@ EMSCRIPTEN_BINDINGS(tests) {
24112427
.function("getString", &HasExternalConstructor::getString)
24122428
;
24132429

2430+
class_<HasExternalConstructorNoCopy>("HasExternalConstructorNoCopy")
2431+
.constructor(&HasExternalConstructorNoCopy::create)
2432+
.function("getInt", &HasExternalConstructorNoCopy::getInt)
2433+
;
2434+
24142435
auto HeldBySmartPtr_class = class_<HeldBySmartPtr>("HeldBySmartPtr");
24152436
HeldBySmartPtr_class
24162437
.smart_ptr<CustomSmartPtr<HeldBySmartPtr>>("CustomSmartPtr<HeldBySmartPtr>")

0 commit comments

Comments
 (0)