Skip to content

Commit 4e848bb

Browse files
committed
Add PropertyDescriptor creation methods
Add static methods on the PropertyDescriptor class that provide convenient ways to construct PropertyDescriptor instances for different kinds of property descriptors. These are equivalent to the similar static methods on the ObjectWrap class, except they are for use when defining properties outside of an object-wrapping scenario. Callbacks are templatized (like with Function::New()) so that they can work with lambdas or regular function pointers. New test cases cover the various overloads for constructing property descriptors and defining properties. And the Name class constructors needed to be made public, to allow code like value.As<Name>(), that is used by the test.
1 parent 7c3b72a commit 4e848bb

File tree

6 files changed

+495
-5
lines changed

6 files changed

+495
-5
lines changed

napi-inl.h

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,35 @@ struct CallbackData<Callable, void> {
10041004
Callable callback;
10051005
};
10061006

1007+
template <typename Getter, typename Setter>
1008+
struct AccessorCallbackData {
1009+
static inline
1010+
napi_value GetterWrapper(napi_env env, napi_callback_info info) {
1011+
try {
1012+
CallbackInfo callbackInfo(env, info);
1013+
AccessorCallbackData* callbackData =
1014+
static_cast<AccessorCallbackData*>(callbackInfo.Data());
1015+
return callbackData->getterCallback(callbackInfo);
1016+
}
1017+
NAPI_RETHROW_JS_ERROR(env)
1018+
}
1019+
1020+
static inline
1021+
napi_value SetterWrapper(napi_env env, napi_callback_info info) {
1022+
try {
1023+
CallbackInfo callbackInfo(env, info);
1024+
AccessorCallbackData* callbackData =
1025+
static_cast<AccessorCallbackData*>(callbackInfo.Data());
1026+
callbackData->setterCallback(callbackInfo);
1027+
return nullptr;
1028+
}
1029+
NAPI_RETHROW_JS_ERROR(env)
1030+
}
1031+
1032+
Getter getterCallback;
1033+
Setter setterCallback;
1034+
};
1035+
10071036
} // namespace details
10081037

10091038
template <typename Callable>
@@ -1740,6 +1769,236 @@ inline void CallbackInfo::SetData(void* data) {
17401769
_data = data;
17411770
}
17421771

1772+
////////////////////////////////////////////////////////////////////////////////
1773+
// PropertyDescriptor class
1774+
////////////////////////////////////////////////////////////////////////////////
1775+
1776+
template <typename Getter>
1777+
inline PropertyDescriptor
1778+
PropertyDescriptor::Accessor(const char* utf8name,
1779+
Getter getter,
1780+
napi_property_attributes attributes,
1781+
void* data) {
1782+
typedef details::CallbackData<Getter, Napi::Value> CbData;
1783+
// TODO: Delete when the function is destroyed
1784+
auto callbackData = new CbData({ getter });
1785+
1786+
return PropertyDescriptor({
1787+
utf8name,
1788+
nullptr,
1789+
nullptr,
1790+
CbData::Wrapper,
1791+
nullptr,
1792+
nullptr,
1793+
attributes,
1794+
callbackData
1795+
});
1796+
}
1797+
1798+
template <typename Getter>
1799+
inline PropertyDescriptor PropertyDescriptor::Accessor(const std::string& utf8name,
1800+
Getter getter,
1801+
napi_property_attributes attributes,
1802+
void* data) {
1803+
return Accessor(utf8name.c_str(), getter, attributes, data);
1804+
}
1805+
1806+
template <typename Getter>
1807+
inline PropertyDescriptor PropertyDescriptor::Accessor(napi_value name,
1808+
Getter getter,
1809+
napi_property_attributes attributes,
1810+
void* data) {
1811+
typedef details::CallbackData<Getter, Napi::Value> CbData;
1812+
// TODO: Delete when the function is destroyed
1813+
auto callbackData = new CbData({ getter });
1814+
1815+
return PropertyDescriptor({
1816+
nullptr,
1817+
name,
1818+
nullptr,
1819+
CbData::Wrapper,
1820+
nullptr,
1821+
nullptr,
1822+
attributes,
1823+
callbackData
1824+
});
1825+
}
1826+
1827+
template <typename Getter>
1828+
inline PropertyDescriptor PropertyDescriptor::Accessor(Name name,
1829+
Getter getter,
1830+
napi_property_attributes attributes,
1831+
void* data) {
1832+
napi_value nameValue = name;
1833+
return PropertyDescriptor::Accessor(nameValue, getter, attributes, data);
1834+
}
1835+
1836+
template <typename Getter, typename Setter>
1837+
inline PropertyDescriptor PropertyDescriptor::Accessor(const char* utf8name,
1838+
Getter getter,
1839+
Setter setter,
1840+
napi_property_attributes attributes,
1841+
void* data) {
1842+
typedef details::AccessorCallbackData<Getter, Setter> CbData;
1843+
// TODO: Delete when the function is destroyed
1844+
auto callbackData = new CbData({ getter, setter });
1845+
1846+
return PropertyDescriptor({
1847+
utf8name,
1848+
nullptr,
1849+
nullptr,
1850+
CbData::GetterWrapper,
1851+
CbData::SetterWrapper,
1852+
nullptr,
1853+
attributes,
1854+
callbackData
1855+
});
1856+
}
1857+
1858+
template <typename Getter, typename Setter>
1859+
inline PropertyDescriptor PropertyDescriptor::Accessor(const std::string& utf8name,
1860+
Getter getter,
1861+
Setter setter,
1862+
napi_property_attributes attributes,
1863+
void* data) {
1864+
return Accessor(utf8name.c_str(), getter, setter, attributes, data);
1865+
}
1866+
1867+
template <typename Getter, typename Setter>
1868+
inline PropertyDescriptor PropertyDescriptor::Accessor(napi_value name,
1869+
Getter getter,
1870+
Setter setter,
1871+
napi_property_attributes attributes,
1872+
void* data) {
1873+
typedef details::AccessorCallbackData<Getter, Setter> CbData;
1874+
// TODO: Delete when the function is destroyed
1875+
auto callbackData = new CbData({ getter, setter });
1876+
1877+
return PropertyDescriptor({
1878+
nullptr,
1879+
name,
1880+
nullptr,
1881+
CbData::GetterWrapper,
1882+
CbData::SetterWrapper,
1883+
nullptr,
1884+
attributes,
1885+
callbackData
1886+
});
1887+
}
1888+
1889+
template <typename Getter, typename Setter>
1890+
inline PropertyDescriptor PropertyDescriptor::Accessor(Name name,
1891+
Getter getter,
1892+
Setter setter,
1893+
napi_property_attributes attributes,
1894+
void* data) {
1895+
napi_value nameValue = name;
1896+
return PropertyDescriptor::Accessor(nameValue, getter, setter, attributes, data);
1897+
}
1898+
1899+
template <typename Callable>
1900+
inline PropertyDescriptor PropertyDescriptor::Function(const char* utf8name,
1901+
Callable cb,
1902+
napi_property_attributes attributes,
1903+
void* data) {
1904+
typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
1905+
typedef details::CallbackData<Callable, ReturnType> CbData;
1906+
// TODO: Delete when the function is destroyed
1907+
auto callbackData = new CbData({ cb });
1908+
1909+
return PropertyDescriptor({
1910+
utf8name,
1911+
nullptr,
1912+
CbData::Wrapper,
1913+
nullptr,
1914+
nullptr,
1915+
nullptr,
1916+
attributes,
1917+
callbackData
1918+
});
1919+
}
1920+
1921+
template <typename Callable>
1922+
inline PropertyDescriptor PropertyDescriptor::Function(const std::string& utf8name,
1923+
Callable cb,
1924+
napi_property_attributes attributes,
1925+
void* data) {
1926+
return Function(utf8name.c_str(), cb, attributes, data);
1927+
}
1928+
1929+
template <typename Callable>
1930+
inline PropertyDescriptor PropertyDescriptor::Function(napi_value name,
1931+
Callable cb,
1932+
napi_property_attributes attributes,
1933+
void* data) {
1934+
typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
1935+
typedef details::CallbackData<Callable, ReturnType> CbData;
1936+
// TODO: Delete when the function is destroyed
1937+
auto callbackData = new CbData({ cb });
1938+
1939+
return PropertyDescriptor({
1940+
nullptr,
1941+
name,
1942+
CbData::Wrapper,
1943+
nullptr,
1944+
nullptr,
1945+
nullptr,
1946+
attributes,
1947+
callbackData
1948+
});
1949+
}
1950+
1951+
template <typename Callable>
1952+
inline PropertyDescriptor PropertyDescriptor::Function(Name name,
1953+
Callable cb,
1954+
napi_property_attributes attributes,
1955+
void* data) {
1956+
napi_value nameValue = name;
1957+
return PropertyDescriptor::Function(nameValue, cb, attributes, data);
1958+
}
1959+
1960+
inline PropertyDescriptor PropertyDescriptor::Value(const char* utf8name,
1961+
napi_value value,
1962+
napi_property_attributes attributes) {
1963+
return PropertyDescriptor({
1964+
utf8name, nullptr, nullptr, nullptr, nullptr, value, attributes, nullptr
1965+
});
1966+
}
1967+
1968+
inline PropertyDescriptor PropertyDescriptor::Value(const std::string& utf8name,
1969+
napi_value value,
1970+
napi_property_attributes attributes) {
1971+
return Value(utf8name.c_str(), value, attributes);
1972+
}
1973+
1974+
inline PropertyDescriptor PropertyDescriptor::Value(napi_value name,
1975+
napi_value value,
1976+
napi_property_attributes attributes) {
1977+
return PropertyDescriptor({
1978+
nullptr, name, nullptr, nullptr, nullptr, value, attributes, nullptr
1979+
});
1980+
}
1981+
1982+
inline PropertyDescriptor PropertyDescriptor::Value(Name name,
1983+
Napi::Value value,
1984+
napi_property_attributes attributes) {
1985+
napi_value nameValue = name;
1986+
napi_value valueValue = value;
1987+
return PropertyDescriptor::Value(nameValue, valueValue, attributes);
1988+
}
1989+
1990+
inline PropertyDescriptor::PropertyDescriptor(napi_property_descriptor desc)
1991+
: _desc(desc) {
1992+
}
1993+
1994+
inline PropertyDescriptor::operator napi_property_descriptor&() {
1995+
return _desc;
1996+
}
1997+
1998+
inline PropertyDescriptor::operator const napi_property_descriptor&() const {
1999+
return _desc;
2000+
}
2001+
17432002
////////////////////////////////////////////////////////////////////////////////
17442003
// ObjectWrap<T> class
17452004
////////////////////////////////////////////////////////////////////////////////

napi.h

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ namespace Napi {
152152
};
153153

154154
class Name : public Value {
155-
protected:
155+
public:
156156
Name();
157157
Name(napi_env env, napi_value value);
158158
};
@@ -651,10 +651,87 @@ namespace Napi {
651651

652652
class PropertyDescriptor {
653653
public:
654-
PropertyDescriptor(napi_property_descriptor desc) : _desc(desc) {}
655-
656-
operator napi_property_descriptor&() { return _desc; }
657-
operator const napi_property_descriptor&() const { return _desc; }
654+
template <typename Getter>
655+
static PropertyDescriptor Accessor(const char* utf8name,
656+
Getter getter,
657+
napi_property_attributes attributes = napi_default,
658+
void* data = nullptr);
659+
template <typename Getter>
660+
static PropertyDescriptor Accessor(const std::string& utf8name,
661+
Getter getter,
662+
napi_property_attributes attributes = napi_default,
663+
void* data = nullptr);
664+
template <typename Getter>
665+
static PropertyDescriptor Accessor(napi_value name,
666+
Getter getter,
667+
napi_property_attributes attributes = napi_default,
668+
void* data = nullptr);
669+
template <typename Getter>
670+
static PropertyDescriptor Accessor(Name name,
671+
Getter getter,
672+
napi_property_attributes attributes = napi_default,
673+
void* data = nullptr);
674+
template <typename Getter, typename Setter>
675+
static PropertyDescriptor Accessor(const char* utf8name,
676+
Getter getter,
677+
Setter setter,
678+
napi_property_attributes attributes = napi_default,
679+
void* data = nullptr);
680+
template <typename Getter, typename Setter>
681+
static PropertyDescriptor Accessor(const std::string& utf8name,
682+
Getter getter,
683+
Setter setter,
684+
napi_property_attributes attributes = napi_default,
685+
void* data = nullptr);
686+
template <typename Getter, typename Setter>
687+
static PropertyDescriptor Accessor(napi_value name,
688+
Getter getter,
689+
Setter setter,
690+
napi_property_attributes attributes = napi_default,
691+
void* data = nullptr);
692+
template <typename Getter, typename Setter>
693+
static PropertyDescriptor Accessor(Name name,
694+
Getter getter,
695+
Setter setter,
696+
napi_property_attributes attributes = napi_default,
697+
void* data = nullptr);
698+
template <typename Callable>
699+
static PropertyDescriptor Function(const char* utf8name,
700+
Callable cb,
701+
napi_property_attributes attributes = napi_default,
702+
void* data = nullptr);
703+
template <typename Callable>
704+
static PropertyDescriptor Function(const std::string& utf8name,
705+
Callable cb,
706+
napi_property_attributes attributes = napi_default,
707+
void* data = nullptr);
708+
template <typename Callable>
709+
static PropertyDescriptor Function(napi_value name,
710+
Callable cb,
711+
napi_property_attributes attributes = napi_default,
712+
void* data = nullptr);
713+
template <typename Callable>
714+
static PropertyDescriptor Function(Name name,
715+
Callable cb,
716+
napi_property_attributes attributes = napi_default,
717+
void* data = nullptr);
718+
static PropertyDescriptor Value(const char* utf8name,
719+
napi_value value,
720+
napi_property_attributes attributes = napi_default);
721+
static PropertyDescriptor Value(const std::string& utf8name,
722+
napi_value value,
723+
napi_property_attributes attributes = napi_default);
724+
static PropertyDescriptor Value(napi_value name,
725+
napi_value value,
726+
napi_property_attributes attributes = napi_default);
727+
static PropertyDescriptor Value(Name name,
728+
Napi::Value value,
729+
napi_property_attributes attributes = napi_default);
730+
731+
PropertyDescriptor(napi_property_descriptor desc);
732+
733+
operator napi_property_descriptor&();
734+
operator const napi_property_descriptor&() const;
658735

659736
private:
660737
napi_property_descriptor _desc;

test/binding.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ using namespace Napi;
55
Object InitError(Env env);
66
Object InitFunction(Env env);
77
Object InitName(Env env);
8+
Object InitObject(Env env);
89

910
void Init(Env env, Object exports, Object module) {
1011
exports.Set("error", InitError(env));
1112
exports.Set("function", InitFunction(env));
1213
exports.Set("name", InitName(env));
14+
exports.Set("object", InitObject(env));
1315
}
1416

1517
NODE_API_MODULE(addon, Init)

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
'error.cc',
88
'function.cc',
99
'name.cc',
10+
'object.cc',
1011
],
1112
'include_dirs': ["<!(node -p \"require('../').include\")"],
1213
'dependencies': ["<!(node -p \"require('../').gyp\")"],

0 commit comments

Comments
 (0)