Page MenuHomePhorge

D7250.1768380683.diff
No OneTemporary

Size
231 KB
Referenced Files
None
Subscribers
None

D7250.1768380683.diff

diff --git a/desktop/addons/windows-pushnotifications/CollectionsConverter.h b/desktop/addons/windows-pushnotifications/CollectionsConverter.h
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/CollectionsConverter.h
@@ -0,0 +1,305 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#pragma once
+#include <collection.h>
+#include <v8.h>
+#include "CollectionsConverterUtils.h"
+#include "NodeRtUtils.h"
+#include "nan.h"
+
+namespace NodeRT
+{
+ namespace Collections
+ {
+
+ Nan::Persistent<v8::String> g_keyProp;
+ Nan::Persistent<v8::String> g_valueProp;
+
+ static void initProps()
+ {
+ if (g_keyProp.IsEmpty())
+ g_keyProp.Reset(Nan::New<v8::String>("key").ToLocalChecked());
+
+ if (g_valueProp.IsEmpty())
+ g_valueProp.Reset(Nan::New<v8::String>("value").ToLocalChecked());
+ }
+
+ static std::function<bool(v8::Local<v8::Value>)> checkStringFunc =
+ [](v8::Local<v8::Value> value) -> bool
+ { return value->IsString(); };
+
+ template <class K, class V>
+ static ::Platform::Collections::Map<K, V> ^
+ JsArrayToWinrtMap(
+ v8::Local<v8::Array> arr,
+ const std::function<bool(v8::Local<v8::Value>)> &checkKeyTypeFunc,
+ const std::function<K(v8::Local<v8::Value>)> &convertToKeyTypeFunc,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc) {
+ std::map<K, V> stdMap;
+ if (!FillMapFromJsArray(arr, checkKeyTypeFunc, convertToKeyTypeFunc,
+ checkValueTypeFunc, convertToValueTypeFunc,
+ stdMap))
+ {
+ return nullptr;
+ }
+
+ // TODO: michfa: consider using std::move (here & everywhere), e.g: return
+ // ref new ::Platform::Collections::Map<K, V>(std::move(stdMap));
+ // std::move will give a more efficient initialization from std::map, will
+ // invalidate stdMap however- some types will throw while moving
+ return ref new ::Platform::Collections::Map<K, V>(stdMap);
+ }
+
+ template <class K, class V>
+ static ::Platform::Collections::MapView<K, V> ^
+ JsArrayToWinrtMapView(
+ v8::Local<v8::Array> arr,
+ const std::function<bool(v8::Local<v8::Value>)> &checkKeyTypeFunc,
+ const std::function<K(v8::Local<v8::Value>)> &convertToKeyTypeFunc,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc) {
+ std::map<K, V> stdMap;
+ if (!FillMapFromJsArray(arr, checkKeyTypeFunc, convertToKeyTypeFunc,
+ checkValueTypeFunc, convertToValueTypeFunc,
+ stdMap))
+ {
+ return nullptr;
+ }
+
+ return ref new ::Platform::Collections::MapView<K, V>(stdMap);
+ }
+
+ // A special implementation for the case were the map's keys are strings
+ // In this case we expect a non-array JS object.
+ template <class V>
+ static ::Platform::Collections::Map<Platform::String ^, V> ^
+ JsObjectToWinrtMap(
+ v8::Local<v8::Object> obj,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc) {
+ std::map<::Platform::String ^, V> stdMap;
+
+ if (!FillMapFromJsObject(
+ obj, checkStringFunc, NodeRT::Utils::V8StringToPlatformString,
+ checkValueTypeFunc, convertToValueTypeFunc, stdMap))
+ {
+ return nullptr;
+ }
+
+ return ref new ::Platform::Collections::Map<::Platform::String ^, V>(
+ stdMap);
+ }
+
+ template <class V>
+ static ::Platform::Collections::MapView<Platform::String ^, V> ^
+ JsObjectToWinrtMapView(
+ v8::Local<v8::Object> obj,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc) {
+ std::map<::Platform::String ^, V> stdMap;
+ if (!FillMapFromJsObject(
+ obj, checkStringFunc, NodeRT::Utils::V8StringToPlatformString,
+ checkValueTypeFunc, convertToValueTypeFunc, stdMap))
+ {
+ return nullptr;
+ }
+
+ return ref new ::Platform::Collections::MapView<::Platform::String ^, V>(
+ stdMap);
+ }
+
+ template <class V>
+ static ::Platform::Collections::Vector<V> ^
+ JsArrayToWinrtVector(
+ v8::Local<v8::Array> arr,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc) {
+ std::vector<V> vec(arr->Length());
+ if (!FillVector<std::vector<V> &, V>(arr, checkValueTypeFunc,
+ convertToValueTypeFunc, vec))
+ {
+ return nullptr;
+ }
+
+ return ref new ::Platform::Collections::Vector<V>(vec);
+ }
+
+ template <class V>
+ static ::Platform::Collections::VectorView<V> ^
+ JsArrayToWinrtVectorView(
+ v8::Local<v8::Array> arr,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc) {
+ std::vector<V> vec(arr->Length());
+
+ if (!FillVector<std::vector<V> &, V>(arr, checkValueTypeFunc,
+ convertToValueTypeFunc, vec))
+ {
+ return nullptr;
+ }
+
+ return ref new ::Platform::Collections::VectorView<V>(vec);
+ }
+
+ template <class V>
+ static ::Platform::Array<V> ^
+ JsArrayToWinrtArray(
+ v8::Local<v8::Array> arr,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc) {
+ auto vec = ref new ::Platform::Array<V>(arr->Length());
+ if (!FillVector<::Platform::Array<V> ^, V>(arr, checkValueTypeFunc,
+ convertToValueTypeFunc, vec))
+ {
+ return nullptr;
+ }
+
+ return vec;
+ }
+ } // namespace Collections
+
+ template <class V>
+ static void InsertToVector(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc,
+ std::vector<V> &vec)
+ {
+ vec[index] = convertToValueTypeFunc(value);
+ }
+
+ template <class V>
+ static void InsertToVector(
+ uint32_t index,
+ v8::Local<v8::Value> value,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc,
+ ::Platform::Array<V> ^ vec)
+ {
+ vec->set(index, convertToValueTypeFunc(value));
+ }
+
+ // assumption: vec length >= arr length
+ template <class T, class V>
+ static bool FillVector(
+ v8::Local<v8::Array> arr,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc,
+ T vec)
+ {
+ for (uint32_t i = 0; i < arr->Length(); i++)
+ {
+ Local<Value> value = Nan::Get(arr, i).ToLocalChecked();
+
+ if (!checkValueTypeFunc(value))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Received array with unexpected value type")));
+ return false;
+ }
+
+ InsertToVector(i, value, convertToValueTypeFunc, vec);
+ }
+
+ return true;
+ }
+
+ template <class K, class V>
+ static bool FillMapFromJsArray(
+ v8::Local<v8::Array> arr,
+ const std::function<bool(v8::Local<v8::Value>)> &checkKeyTypeFunc,
+ const std::function<K(v8::Local<v8::Value>)> &convertToKeyTypeFunc,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc,
+ std::map<K, V> &stdMap)
+ {
+ initProps();
+
+ // expect that each element in the array will be an object with 2 properties:
+ // key and value (with types that match K and V respectively)
+ for (uint32_t i = 0; i < arr->Length(); i++)
+ {
+ Local<Value> curr = Nan::Get(arr, i).ToLocalChecked();
+
+ if (!curr->IsObject())
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Array elements are expected to be javascript objects")));
+ return false;
+ }
+
+ v8::Local<v8::Object> obj = curr.As<v8::Object>();
+
+ if (!obj->Has(g_keyProp) || !obj->Has(g_valueProp))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Array elements are expected to be javascript objects with \'key\' "
+ L"and \'value\' properties")));
+ return false;
+ }
+
+ Local<Value> key = Nan::Get(obj, g_keyProp).ToLocalChecked();
+ Local<Value> value = Nan::Get(obj, g_valueProp).ToLocalChecked();
+
+ if (!checkKeyTypeFunc(key))
+ {
+ Nan::ThrowError(Nan::Error(
+ NodeRT::Utils::NewString(L"Array element has invalid key type")));
+ return false;
+ }
+
+ if (!checkValueTypeFunc(value))
+ {
+ Nan::ThrowError(Nan::Error(
+ NodeRT::Utils::NewString(L"Array element has invalid value type")));
+ return false;
+ }
+
+ stdMap.insert(std::pair<K, V>(convertToKeyTypeFunc(key),
+ convertToValueTypeFunc(value)));
+ }
+
+ return true;
+ }
+
+ template <class V>
+ static bool FillMapFromJsObject(
+ v8::Local<v8::Object> obj,
+ const std::function<bool(v8::Local<v8::Value>)> &checkKeyTypeFunc,
+ const std::function<::Platform::String ^ (v8::Local<v8::Value>)> &
+ convertToKeyTypeFunc,
+ const std::function<bool(v8::Local<v8::Value>)> &checkValueTypeFunc,
+ const std::function<V(v8::Local<v8::Value>)> &convertToValueTypeFunc,
+ std::map<::Platform::String ^, V> &stdMap)
+ {
+ Local<Array> objProps = Nan::GetPropertyNames(obj).ToLocalChecked();
+ for (uint32_t i = 0; i < objProps->Length(); i++)
+ {
+ Local<Value> key = Nan::Get(objProps, i).ToLocalChecked();
+ Local<Value> value = Nan::Get(obj, key).ToLocalChecked();
+ if (!checkValueTypeFunc(value))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Received object with unexpected value type")));
+ return false;
+ }
+
+ stdMap.insert(std::pair<::Platform::String ^, V>(
+ convertToKeyTypeFunc(key), convertToValueTypeFunc(value)));
+ }
+ return true;
+ }
+}; // namespace NodeRT
diff --git a/desktop/addons/windows-pushnotifications/CollectionsConverterUtils.h b/desktop/addons/windows-pushnotifications/CollectionsConverterUtils.h
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/CollectionsConverterUtils.h
@@ -0,0 +1,38 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#pragma once
+
+// Every type used in Vector or VectorView template instantiation must have
+// operator== Implement operator== for types that don't have an operator==
+// implementation available and there is no acceptable conversion to an existing
+// operator==
+namespace std
+{
+
+ bool operator==(const ::Windows::Foundation::TimeSpan &first,
+ const ::Windows::Foundation::TimeSpan &second);
+
+ bool operator==(
+ const ::Windows::Devices::Geolocation::BasicGeoposition &first,
+ const ::Windows::Devices::Geolocation::BasicGeoposition &second);
+
+ bool operator==(const ::Windows::Storage::Search::SortEntry &first,
+ const ::Windows::Storage::Search::SortEntry &second);
+
+ bool operator==(const ::Windows::Data::Text::TextSegment &first,
+ const ::Windows::Data::Text::TextSegment &second);
+
+} // namespace std
diff --git a/desktop/addons/windows-pushnotifications/CollectionsConverterUtils.cpp b/desktop/addons/windows-pushnotifications/CollectionsConverterUtils.cpp
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/CollectionsConverterUtils.cpp
@@ -0,0 +1,49 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#include "CollectionsConverterUtils.h"
+
+namespace std
+{
+ bool operator==(const ::Windows::Foundation::TimeSpan &first,
+ const ::Windows::Foundation::TimeSpan &second)
+ {
+ return first.Duration == second.Duration;
+ }
+
+ bool operator==(
+ const ::Windows::Devices::Geolocation::BasicGeoposition &first,
+ const ::Windows::Devices::Geolocation::BasicGeoposition &second)
+ {
+ return (first.Altitude == second.Altitude) &&
+ (first.Latitude == second.Latitude) &&
+ (first.Longitude == second.Longitude);
+ }
+
+ bool operator==(const ::Windows::Storage::Search::SortEntry &first,
+ const ::Windows::Storage::Search::SortEntry &second)
+ {
+ return (first.AscendingOrder == second.AscendingOrder) &&
+ (first.PropertyName == second.PropertyName);
+ }
+
+ bool operator==(const ::Windows::Data::Text::TextSegment &first,
+ const ::Windows::Data::Text::TextSegment &second)
+ {
+ return (first.Length == second.Length) &&
+ (first.StartPosition == second.StartPosition);
+ }
+
+} // namespace std
diff --git a/desktop/addons/windows-pushnotifications/CollectionsWrap.h b/desktop/addons/windows-pushnotifications/CollectionsWrap.h
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/CollectionsWrap.h
@@ -0,0 +1,2363 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+#pragma once
+
+#include <v8.h>
+#include "NodeRtUtils.h"
+#include "OpaqueWrapper.h"
+#include "WrapperBase.h"
+#include "nan.h"
+
+#include <functional>
+
+namespace NodeRT
+{
+ namespace Collections
+ {
+
+ using Nan::False;
+ using Nan::HandleScope;
+ using Nan::MaybeLocal;
+ using Nan::Null;
+ using Nan::Persistent;
+ using Nan::True;
+ using Nan::Undefined;
+ using v8::Boolean;
+ using v8::FunctionTemplate;
+ using v8::Integer;
+ using v8::Local;
+ using v8::String;
+ using v8::Value;
+
+ template <class T>
+ class ArrayWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ EscapableHandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Array").ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+ Nan::SetIndexedPropertyHandler(localRef->InstanceTemplate(), Get, Set);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("length").ToLocalChecked(), LengthGetter);
+
+ return;
+ }
+
+ static Local<Value> CreateArrayWrapper(
+ ::Platform::Array<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc = nullptr,
+ const std::function<bool(Local<Value>)> &checkTypeFunc = nullptr,
+ const std::function<T(Local<Value>)> &convertToTypeFunc = nullptr)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ ArrayWrapper<T> *wrapperInstance = new ArrayWrapper<T>(
+ winRtInstance, getterFunc, checkTypeFunc, convertToTypeFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ ArrayWrapper(
+ ::Platform::Array<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc,
+ const std::function<bool(Local<Value>)> &checkTypeFunc = nullptr,
+ const std::function<T(Local<Value>)> &convertToTypeFunc = nullptr)
+ : _instance(winRtInstance),
+ _getterFunc(getterFunc),
+ _checkTypeFunc(checkTypeFunc),
+ _convertToTypeFunc(convertToTypeFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void LengthGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ ArrayWrapper<T> *wrapper =
+ ArrayWrapper<T>::Unwrap<ArrayWrapper<T>>(info.This());
+
+ try
+ {
+ unsigned int result = wrapper->_instance->Length;
+ info.GetReturnValue().Set(Nan::New<Integer>(result));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void Get(uint32_t index,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ ArrayWrapper<T> *wrapper =
+ ArrayWrapper<T>::Unwrap<ArrayWrapper<T>>(info.This());
+
+ if (wrapper->_instance->Length <= index)
+ {
+ return;
+ }
+
+ if (wrapper->_getterFunc == nullptr)
+ {
+ info.GetReturnValue().Set(CreateOpaqueWrapper(wrapper->_instance[index]));
+ }
+ else
+ {
+ info.GetReturnValue().Set(
+ wrapper->_getterFunc(wrapper->_instance[index]));
+ }
+ }
+
+ static void Set(uint32_t index,
+ Local<Value> value,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ ArrayWrapper<T> *wrapper =
+ ArrayWrapper<T>::Unwrap<ArrayWrapper<T>>(info.This());
+
+ if (wrapper->_checkTypeFunc && !wrapper->_checkTypeFunc(value))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"The argument to set isn't of the expected type or internal WinRt "
+ L"object was disposed")));
+ return;
+ }
+
+ if (wrapper->_instance->Length <= index)
+ {
+ Nan::ThrowError(Nan::Error(
+ NodeRT::Utils::NewString(L"Given index exceeded array length")));
+ return;
+ }
+
+ if (wrapper->_convertToTypeFunc)
+ {
+ try
+ {
+ wrapper->_instance[index] = wrapper->_convertToTypeFunc(value);
+ }
+ catch (::Platform::Exception ^ e)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(e);
+ }
+ }
+
+ return;
+ }
+
+ private:
+ ::Platform::Array<T> ^ _instance;
+ std::function<Local<Value>(T)> _getterFunc;
+ std::function<bool(Local<Value>)> _checkTypeFunc;
+ std::function<T(Local<Value>)> _convertToTypeFunc;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class T>
+ Persistent<FunctionTemplate> ArrayWrapper<T>::s_constructorTemplate;
+
+ template <class T>
+ class IteratorWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Collections:IIterator")
+ .ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetPrototypeMethod(localRef, "getMany", GetMany);
+ Nan::SetPrototypeMethod(localRef, "moveNext", MoveNext);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("current").ToLocalChecked(),
+ CurrentGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("hasCurrent").ToLocalChecked(),
+ HasCurrentGetter);
+
+ return;
+ }
+
+ static Local<Value> CreateIteratorWrapper(
+ ::Windows::Foundation::Collections::IIterator<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc = nullptr)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ IteratorWrapper<T> *wrapperInstance =
+ new IteratorWrapper<T>(winRtInstance, getterFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ IteratorWrapper(::Windows::Foundation::Collections::IIterator<T> ^
+ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc)
+ : _instance(winRtInstance), _getterFunc(getterFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void MoveNext(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IIterator<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ IteratorWrapper<T> *wrapper =
+ IteratorWrapper<T>::Unwrap<IteratorWrapper<T>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ bool result;
+ result = wrapper->_instance->MoveNext();
+ info.GetReturnValue().Set(Nan::New<Boolean>(result));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ // Not supporting this for now since we need to initialize the array ourselves
+ // and don't know which size to use
+ static void GetMany(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Not implemented")));
+ return;
+ }
+
+ static void CurrentGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IIterator<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ IteratorWrapper<T> *wrapper =
+ IteratorWrapper<T>::Unwrap<IteratorWrapper<T>>(info.This());
+
+ try
+ {
+ T current = wrapper->_instance->Current;
+
+ if (wrapper->_getterFunc != nullptr)
+ {
+ info.GetReturnValue().Set(wrapper->_getterFunc(current));
+ }
+ else
+ {
+ info.GetReturnValue().Set(CreateOpaqueWrapper(current));
+ }
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void HasCurrentGetter(
+ Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IIterator<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ IteratorWrapper<T> *wrapper =
+ IteratorWrapper<T>::Unwrap<IteratorWrapper<T>>(info.This());
+
+ try
+ {
+ bool result = wrapper->_instance->HasCurrent;
+ info.GetReturnValue().Set(Nan::New<Boolean>(result));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Windows::Foundation::Collections::IIterator<T> ^ _instance;
+ std::function<Local<Value>(T)> _getterFunc;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class T>
+ class IterableWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Collections:IIterable")
+ .ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetPrototypeMethod(localRef, "first", First);
+
+ return;
+ }
+
+ static Local<Value> CreateIterableWrapper(
+ ::Windows::Foundation::Collections::IIterable<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc = nullptr)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ IterableWrapper<T> *wrapperInstance =
+ new IterableWrapper<T>(winRtInstance, getterFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ IterableWrapper(::Windows::Foundation::Collections::IIterable<T> ^
+ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc)
+ : _instance(winRtInstance), _getterFunc(getterFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This().Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void First(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IIterable<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ IterableWrapper<T> *wrapper =
+ IterableWrapper<T>::Unwrap<IterableWrapper<T>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ ::Windows::Foundation::Collections::IIterator<T> ^ result =
+ wrapper->_instance->First();
+
+ info.GetReturnValue().Set(IteratorWrapper<T>::CreateIteratorWrapper(
+ result, wrapper->_getterFunc));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ private:
+ ::Windows::Foundation::Collections::IIterable<T> ^ _instance;
+ std::function<Local<Value>(T)> _getterFunc;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class T>
+ Persistent<FunctionTemplate> IterableWrapper<T>::s_constructorTemplate;
+
+ template <class T>
+ Persistent<FunctionTemplate> IteratorWrapper<T>::s_constructorTemplate;
+
+ template <class T>
+ class VectorViewWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Collections:IVectorView")
+ .ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+ Nan::SetIndexedPropertyHandler(localRef->InstanceTemplate(), Get);
+
+ Nan::SetPrototypeMethod(localRef, "getMany", GetMany);
+ Nan::SetPrototypeMethod(localRef, "getAt", GetAt);
+ Nan::SetPrototypeMethod(localRef, "indexOf", IndexOf);
+ Nan::SetPrototypeMethod(localRef, "first", First);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("size").ToLocalChecked(), SizeGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("length").ToLocalChecked(), SizeGetter);
+
+ return;
+ }
+
+ static Local<Value> CreateVectorViewWrapper(
+ ::Windows::Foundation::Collections::IVectorView<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc,
+ const std::function<bool(Local<Value>)> &checkTypeFunc = nullptr,
+ const std::function<T(Local<Value>)> &convertToTypeFunc = nullptr)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ VectorViewWrapper<T> *wrapperInstance =
+ new VectorViewWrapper<T>(winRtInstance, getterFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ VectorViewWrapper(
+ ::Windows::Foundation::Collections::IVectorView<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc,
+ const std::function<bool(Local<Value>)> &checkTypeFunc = nullptr,
+ const std::function<T(Local<Value>)> &convertToTypeFunc = nullptr)
+ : _instance(winRtInstance),
+ _getterFunc(getterFunc),
+ _checkTypeFunc(checkTypeFunc),
+ _convertToTypeFunc(convertToTypeFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void Get(uint32_t index,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVectorView<T> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ VectorViewWrapper<T> *wrapper =
+ VectorViewWrapper<T>::Unwrap<VectorViewWrapper<T>>(info.This());
+
+ if (wrapper->_instance->Size <= index)
+ {
+ return;
+ }
+
+ if (wrapper->_getterFunc == nullptr)
+ {
+ info.GetReturnValue().Set(
+ CreateOpaqueWrapper(wrapper->_instance->GetAt(index)));
+ }
+ else
+ {
+ info.GetReturnValue().Set(
+ wrapper->_getterFunc(wrapper->_instance->GetAt(index)));
+ }
+ }
+
+ static void GetAt(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVectorView<T> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ VectorViewWrapper<T> *wrapper =
+ VectorViewWrapper<T>::Unwrap<VectorViewWrapper<T>>(info.This());
+
+ if (info.Length() == 1 && info[0]->IsUint32())
+ {
+ try
+ {
+ unsigned int index = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
+
+ if (index >= wrapper->_instance->Size)
+ {
+ return;
+ }
+ T result;
+ result = wrapper->_instance->GetAt(index);
+
+ if (wrapper->_getterFunc)
+ {
+ info.GetReturnValue().Set(wrapper->_getterFunc(result));
+ }
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void GetMany(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Not implemented")));
+ return;
+ }
+
+ static void First(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVectorView<T> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ VectorViewWrapper<T> *wrapper =
+ VectorViewWrapper<T>::Unwrap<VectorViewWrapper<T>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ info.GetReturnValue().Set(IteratorWrapper<T>::CreateIteratorWrapper(
+ wrapper->_instance->First(), wrapper->_getterFunc));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void IndexOf(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVectorView<T> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ VectorViewWrapper<T> *wrapper =
+ VectorViewWrapper<T>::Unwrap<VectorViewWrapper<T>>(info.This());
+
+ if (wrapper->_convertToTypeFunc == nullptr ||
+ wrapper->_checkTypeFunc == nullptr)
+ {
+ Nan::ThrowError(
+ Nan::Error(NodeRT::Utils::NewString(L"Method isn't supported")));
+ return;
+ }
+
+ if (info.Length() == 1 && wrapper->_checkTypeFunc(info[0]))
+ {
+ try
+ {
+ T item = wrapper->_convertToTypeFunc(info[0]);
+
+ unsigned int index;
+ bool result = wrapper->_instance->IndexOf(item, &index);
+
+ Local<Object> resObj = Nan::New<Object>();
+ Nan::Set(resObj, Nan::New<String>("boolean").ToLocalChecked(),
+ Nan::New<v8::Boolean>(result));
+ Nan::Set(resObj, Nan::New<String>("index").ToLocalChecked(),
+ Nan::New<v8::Integer>(index));
+ info.GetReturnValue().Set(resObj);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void SizeGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVectorView<T> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ VectorViewWrapper<T> *wrapper =
+ VectorViewWrapper<T>::Unwrap<VectorViewWrapper<T>>(info.This());
+
+ try
+ {
+ info.GetReturnValue().Set(Nan::New<Integer>(wrapper->_instance->Size));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Windows::Foundation::Collections::IVectorView<T> ^ _instance;
+ std::function<Local<Value>(T)> _getterFunc;
+ std::function<bool(Local<Value>)> _checkTypeFunc;
+ std::function<T(Local<Value>)> _convertToTypeFunc;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class T>
+ Persistent<FunctionTemplate> VectorViewWrapper<T>::s_constructorTemplate;
+
+ template <class T>
+ class VectorWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Collections:IVector")
+ .ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+ Nan::SetIndexedPropertyHandler(localRef->InstanceTemplate(), Get, Set);
+
+ Nan::SetPrototypeMethod(localRef, "getMany", GetMany);
+ Nan::SetPrototypeMethod(localRef, "getAt", GetAt);
+ Nan::SetPrototypeMethod(localRef, "indexOf", IndexOf);
+ Nan::SetPrototypeMethod(localRef, "first", First);
+ Nan::SetPrototypeMethod(localRef, "append", Append);
+ Nan::SetPrototypeMethod(localRef, "clear", Clear);
+ Nan::SetPrototypeMethod(localRef, "getView", GetView);
+ Nan::SetPrototypeMethod(localRef, "insertAt", InsertAt);
+ Nan::SetPrototypeMethod(localRef, "removeAt", RemoveAt);
+ Nan::SetPrototypeMethod(localRef, "removeAtEnd", RemoveAtEnd);
+ Nan::SetPrototypeMethod(localRef, "replaceAll", ReplaceAll);
+ Nan::SetPrototypeMethod(localRef, "setAt", SetAt);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("size").ToLocalChecked(), SizeGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("length").ToLocalChecked(), SizeGetter);
+
+ return;
+ }
+
+ static Local<Value> CreateVectorWrapper(
+ ::Windows::Foundation::Collections::IVector<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc,
+ const std::function<bool(Local<Value>)> &checkTypeFunc = nullptr,
+ const std::function<T(Local<Value>)> &convertToTypeFunc = nullptr)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ VectorWrapper<T> *wrapperInstance = new VectorWrapper<T>(
+ winRtInstance, getterFunc, checkTypeFunc, convertToTypeFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ VectorWrapper(
+ ::Windows::Foundation::Collections::IVector<T> ^ winRtInstance,
+ const std::function<Local<Value>(T)> &getterFunc,
+ const std::function<bool(Local<Value>)> &checkTypeFunc = nullptr,
+ const std::function<T(Local<Value>)> &convertToTypeFunc = nullptr)
+ : _instance(winRtInstance),
+ _getterFunc(getterFunc),
+ _checkTypeFunc(checkTypeFunc),
+ _convertToTypeFunc(convertToTypeFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void Get(uint32_t index,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (wrapper->_instance->Size <= index)
+ {
+ return;
+ }
+
+ if (wrapper->_getterFunc == nullptr)
+ {
+ info.GetReturnValue().Set(
+ CreateOpaqueWrapper(wrapper->_instance->GetAt(index)));
+ }
+ else
+ {
+ info.GetReturnValue().Set(
+ wrapper->_getterFunc(wrapper->_instance->GetAt(index)));
+ }
+ }
+
+ static void Set(uint32 index,
+ Local<Value> value,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (!wrapper->_checkTypeFunc(value))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"The value to set isn't of the expected type")));
+ return;
+ }
+
+ try
+ {
+ T item = wrapper->_convertToTypeFunc(value);
+
+ wrapper->_instance->SetAt(index, item);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+
+ return;
+ }
+
+ static void Append(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 1 && wrapper->_checkTypeFunc(info[0]))
+ {
+ try
+ {
+ T value = wrapper->_convertToTypeFunc(info[0]);
+
+ wrapper->_instance->Append(value);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void Clear(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ wrapper->_instance->Clear();
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void GetMany(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Not implemented")));
+ return;
+ }
+
+ static void GetView(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ ::Windows::Foundation::Collections::IVectorView<T> ^ result =
+ wrapper->_instance->GetView();
+ info.GetReturnValue().Set(VectorViewWrapper<T>::CreateVectorViewWrapper(
+ result, wrapper->_getterFunc, wrapper->_checkTypeFunc,
+ wrapper->_convertToTypeFunc));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void InsertAt(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 2 && info[0]->IsUint32() &&
+ wrapper->_checkTypeFunc(info[1]))
+ {
+ try
+ {
+ unsigned int index = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
+
+ T value = wrapper->_convertToTypeFunc(info[1]);
+ wrapper->_instance->InsertAt(index, value);
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void RemoveAt(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 1 && info[0]->IsUint32())
+ {
+ try
+ {
+ unsigned int index = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
+
+ wrapper->_instance->RemoveAt(index);
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void RemoveAtEnd(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ wrapper->_instance->RemoveAtEnd();
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void ReplaceAll(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 1 &&
+ NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<T> ^>(info[0]))
+ {
+ try
+ {
+ WrapperBase *itemsWrapper =
+ WrapperBase::Unwrap<WrapperBase>(info[0].As<Object>());
+ ::Platform::Array<T> ^ items =
+ (::Platform::Array<T> ^) itemsWrapper->GetObjectInstance();
+ wrapper->_instance->ReplaceAll(items);
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void GetAt(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 1 && info[0]->IsUint32())
+ {
+ try
+ {
+ unsigned int index = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
+
+ if (index >= wrapper->_instance->Size)
+ {
+ return;
+ }
+ T result;
+ result = wrapper->_instance->GetAt(index);
+
+ if (wrapper->_getterFunc)
+ {
+ info.GetReturnValue().Set(wrapper->_getterFunc(result));
+ }
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void SetAt(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 2 && info[0]->IsUint32() &&
+ wrapper->_checkTypeFunc(info[1]))
+ {
+ try
+ {
+ unsigned int index = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
+
+ if (index >= wrapper->_instance->Size)
+ {
+ return;
+ }
+
+ T item = wrapper->_convertToTypeFunc(info[1]);
+
+ wrapper->_instance->SetAt(index, item);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void First(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ info.GetReturnValue().Set(IteratorWrapper<T>::CreateIteratorWrapper(
+ wrapper->_instance->First(), wrapper->_getterFunc));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void IndexOf(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ if (wrapper->_convertToTypeFunc == nullptr ||
+ wrapper->_checkTypeFunc == nullptr)
+ {
+ Nan::ThrowError(
+ Nan::Error(NodeRT::Utils::NewString(L"Method isn't supported")));
+ return;
+ }
+
+ if (info.Length() == 1 && wrapper->_checkTypeFunc(info[0]))
+ {
+ try
+ {
+ T item = wrapper->_convertToTypeFunc(info[0]);
+
+ unsigned int index;
+ bool result = wrapper->_instance->IndexOf(item, &index);
+
+ Local<Object> resObj = Nan::New<Object>();
+ Nan::Set(resObj, Nan::New<String>("boolean").ToLocalChecked(),
+ Nan::New<Boolean>(result));
+ Nan::Set(resObj, Nan::New<String>("index").ToLocalChecked(),
+ Nan::New<Integer>(index));
+ info.GetReturnValue().Set(resObj);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void SizeGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IVector<T> ^>(info.This()))
+ {
+ return;
+ }
+
+ VectorWrapper<T> *wrapper =
+ VectorWrapper<T>::Unwrap<VectorWrapper<T>>(info.This());
+
+ try
+ {
+ info.GetReturnValue().Set(Nan::New<Integer>(wrapper->_instance->Size));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Windows::Foundation::Collections::IVector<T> ^ _instance;
+ std::function<Local<Value>(T)> _getterFunc;
+ std::function<bool(Local<Value>)> _checkTypeFunc;
+ std::function<T(Local<Value>)> _convertToTypeFunc;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class T>
+ Persistent<FunctionTemplate> VectorWrapper<T>::s_constructorTemplate;
+
+ template <class K, class V>
+ class KeyValuePairWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Collections:IKeyValuePair")
+ .ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("key").ToLocalChecked(), KeyGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("value").ToLocalChecked(), ValueGetter);
+
+ return;
+ }
+
+ static Local<Value> CreateKeyValuePairWrapper(
+ ::Windows::Foundation::Collections::IKeyValuePair<K, V> ^ winRtInstance,
+ const std::function<Local<Value>(K)> &keyGetterFunc,
+ const std::function<Local<Value>(V)> &valueGetterFunc)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ KeyValuePairWrapper<K, V> *wrapperInstance = new KeyValuePairWrapper<K, V>(
+ winRtInstance, keyGetterFunc, valueGetterFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ KeyValuePairWrapper(::Windows::Foundation::Collections::IKeyValuePair<K, V> ^
+ winRtInstance,
+ const std::function<Local<Value>(K)> &keyGetterFunc,
+ const std::function<Local<Value>(V)> &valueGetterFunc)
+ : _instance(winRtInstance),
+ _keyGetterFunc(keyGetterFunc),
+ _valueGetterFunc(valueGetterFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void KeyGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IKeyValuePair<K, V> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ KeyValuePairWrapper<K, V> *wrapper =
+ KeyValuePairWrapper<K, V>::Unwrap<KeyValuePairWrapper<K, V>>(
+ info.This());
+
+ try
+ {
+ info.GetReturnValue().Set(
+ wrapper->_keyGetterFunc(wrapper->_instance->Key));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void ValueGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IKeyValuePair<K, V> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ KeyValuePairWrapper<K, V> *wrapper =
+ KeyValuePairWrapper<K, V>::Unwrap<KeyValuePairWrapper<K, V>>(
+ info.This());
+
+ try
+ {
+ info.GetReturnValue().Set(
+ wrapper->_valueGetterFunc(wrapper->_instance->Value));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Windows::Foundation::Collections::IKeyValuePair<K, V> ^ _instance;
+ std::function<Local<Value>(K)> _keyGetterFunc;
+ std::function<Local<Value>(V)> _valueGetterFunc;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class K, class V>
+ Persistent<FunctionTemplate> KeyValuePairWrapper<K, V>::s_constructorTemplate;
+
+ template <class K, class V>
+ class MapViewWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Collections:IMapView")
+ .ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetPrototypeMethod(localRef, "hasKey", HasKey);
+ Nan::SetPrototypeMethod(localRef, "lookup", Lookup);
+ Nan::SetPrototypeMethod(localRef, "split", Split);
+ Nan::SetPrototypeMethod(localRef, "first", First);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("size").ToLocalChecked(), SizeGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("length").ToLocalChecked(), SizeGetter);
+
+ return;
+ }
+
+ static Local<Value> CreateMapViewWrapper(
+ ::Windows::Foundation::Collections::IMapView<K, V> ^ winRtInstance,
+ const std::function<Local<Value>(K)> &keyGetterFunc,
+ const std::function<bool(Local<Value>)> &checkKeyTypeFunc,
+ const std::function<K(Local<Value>)> &convertToKeyTypeFunc,
+ const std::function<Local<Value>(V)> &valueGetterFunc)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ MapViewWrapper<K, V> *wrapperInstance =
+ new MapViewWrapper<K, V>(winRtInstance, keyGetterFunc, checkKeyTypeFunc,
+ convertToKeyTypeFunc, valueGetterFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ MapViewWrapper(::Windows::Foundation::Collections::IMapView<K, V> ^
+ winRtInstance,
+ const std::function<Local<Value>(K)> &keyGetterFunc,
+ const std::function<bool(Local<Value>)> &checkKeyTypeFunc,
+ const std::function<K(Local<Value>)> &convertToKeyTypeFunc,
+ const std::function<Local<Value>(V)> &valueGetterFunc)
+ : _instance(winRtInstance),
+ _keyGetterFunc(keyGetterFunc),
+ _checkKeyTypeFunc(checkKeyTypeFunc),
+ _convertToKeyTypeFunc(convertToKeyTypeFunc),
+ _valueGetterFunc(valueGetterFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void HasKey(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMapView<K, V> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ MapViewWrapper<K, V> *wrapper =
+ MapViewWrapper<K, V>::Unwrap<MapViewWrapper<K, V>>(info.This());
+
+ if (info.Length() == 1 && wrapper->_checkKeyTypeFunc(info[0]))
+ {
+ try
+ {
+ K key = wrapper->_convertToKeyTypeFunc(info[0]);
+
+ bool result = wrapper->_instance->HasKey(key);
+
+ info.GetReturnValue().Set(Nan::New<Boolean>(result));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void First(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMapView<K, V> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ MapViewWrapper<K, V> *wrapper =
+ MapViewWrapper<K, V>::Unwrap<MapViewWrapper<K, V>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ const std::function<Local<Value>(K)> &keyGetter =
+ wrapper->_keyGetterFunc;
+ const std::function<Local<Value>(V)> &valueGetter =
+ wrapper->_valueGetterFunc;
+ info.GetReturnValue().Set(
+ IteratorWrapper<
+ ::Windows::Foundation::Collections::IKeyValuePair<K, V> ^>::
+ CreateIteratorWrapper(
+ wrapper->_instance->First(),
+ [keyGetter, valueGetter](
+ ::Windows::Foundation::Collections::IKeyValuePair<K,
+ V> ^
+ value)
+ {
+ return KeyValuePairWrapper<
+ K, V>::CreateKeyValuePairWrapper(value, keyGetter,
+ valueGetter);
+ }));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void Lookup(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMapView<K, V> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ MapViewWrapper<K, V> *wrapper =
+ MapViewWrapper<K, V>::Unwrap<MapViewWrapper<K, V>>(info.This());
+
+ if (info.Length() == 1 && wrapper->_checkKeyTypeFunc(info[0]))
+ {
+ try
+ {
+ K key = wrapper->_convertToKeyTypeFunc(info[0]);
+
+ V result = wrapper->_instance->Lookup(key);
+
+ info.GetReturnValue().Set(wrapper->_valueGetterFunc(result));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void Split(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMapView<K, V> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ MapViewWrapper<K, V> *wrapper =
+ MapViewWrapper<K, V>::Unwrap<MapViewWrapper<K, V>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ ::Windows::Foundation::Collections::IMapView<K, V> ^ first;
+ ::Windows::Foundation::Collections::IMapView<K, V> ^ second;
+
+ wrapper->_instance->Split(&first, &second);
+
+ Local<Object> resObj = Nan::New<Object>();
+ Nan::Set(
+ resObj, Nan::New<String>("first").ToLocalChecked(),
+ MapViewWrapper<K, V>::CreateMapViewWrapper(
+ first, wrapper->_keyGetterFunc, wrapper->_checkTypeFunc,
+ wrapper->_convertToKeyTypeFunc, wrapper->_valueGetterFunc));
+ Nan::Set(
+ resObj, Nan::New<String>("second").ToLocalChecked(),
+ MapViewWrapper<K, V>::CreateMapViewWrapper(
+ second, wrapper->_keyGetterFunc, wrapper->_checkTypeFunc,
+ wrapper->_convertToKeyTypeFunc, wrapper->_valueGetterFunc));
+ info.GetReturnValue().Set(resObj);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void SizeGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMapView<K, V> ^>(
+ info.This()))
+ {
+ return;
+ }
+
+ MapViewWrapper<K, V> *wrapper =
+ MapViewWrapper<K, V>::Unwrap<MapViewWrapper<K, V>>(info.This());
+
+ try
+ {
+ info.GetReturnValue().Set(Nan::New<Integer>(wrapper->_instance->Size));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Windows::Foundation::Collections::IMapView<K, V> ^ _instance;
+ std::function<bool(Local<Value>)> _checkTypeFunc;
+ std::function<Local<Value>(K)> _keyGetterFunc;
+ std::function<K(Local<Value>)> _convertToKeyTypeFunc;
+ std::function<Local<Value>(V)> _valueGetterFunc;
+ std::function<bool(Local<Value>)> _checkKeyTypeFunc;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class K, class V>
+ Persistent<FunctionTemplate> MapViewWrapper<K, V>::s_constructorTemplate;
+
+ template <class K, class V>
+ class MapWrapper : NodeRT::WrapperBase
+ {
+ public:
+ static void Init()
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(
+ Nan::New<String>("Windows::Foundation::Collections:IMap")
+ .ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetPrototypeMethod(localRef, "hasKey", HasKey);
+ Nan::SetPrototypeMethod(localRef, "lookup", Lookup);
+ Nan::SetPrototypeMethod(localRef, "getView", GetView);
+ Nan::SetPrototypeMethod(localRef, "clear", Clear);
+ Nan::SetPrototypeMethod(localRef, "insert", Insert);
+ Nan::SetPrototypeMethod(localRef, "remove", Remove);
+ Nan::SetPrototypeMethod(localRef, "first", First);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("size").ToLocalChecked(), SizeGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(),
+ Nan::New<String>("length").ToLocalChecked(), SizeGetter);
+
+ return;
+ }
+
+ static Local<Value> CreateMapWrapper(
+ ::Windows::Foundation::Collections::IMap<K, V> ^ winRtInstance,
+ const std::function<Local<Value>(K)> &keyGetterFunc,
+ const std::function<bool(Local<Value>)> &checkKeyTypeFunc,
+ const std::function<K(Local<Value>)> &convertToKeyTypeFunc,
+ const std::function<Local<Value>(V)> &valueGetterFunc,
+ const std::function<bool(Local<Value>)> &checkValueTypeFunc,
+ const std::function<V(Local<Value>)> &convertToValueTypeFunc)
+ {
+ EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ if (s_constructorTemplate.IsEmpty())
+ {
+ Init();
+ }
+
+ v8::Local<Value> args[] = {Undefined()};
+ Local<FunctionTemplate> localRef =
+ Nan::New<FunctionTemplate>(s_constructorTemplate);
+ Local<Object> objectInstance =
+ Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args)
+ .ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Undefined());
+ }
+
+ MapWrapper<K, V> *wrapperInstance = new MapWrapper<K, V>(
+ winRtInstance, keyGetterFunc, checkKeyTypeFunc, convertToKeyTypeFunc,
+ valueGetterFunc, checkValueTypeFunc, convertToValueTypeFunc);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ MapWrapper(::Windows::Foundation::Collections::IMap<K, V> ^ winRtInstance,
+ const std::function<Local<Value>(K)> &keyGetterFunc,
+ const std::function<bool(Local<Value>)> &checkKeyTypeFunc,
+ const std::function<K(Local<Value>)> &convertToKeyTypeFunc,
+ const std::function<Local<Value>(V)> &valueGetterFunc,
+ const std::function<bool(Local<Value>)> &checkValueTypeFunc,
+ const std::function<V(Local<Value>)> &convertToValueTypeFunc)
+ : _instance(winRtInstance),
+ _keyGetterFunc(keyGetterFunc),
+ _checkKeyTypeFunc(checkKeyTypeFunc),
+ _convertToKeyTypeFunc(convertToKeyTypeFunc),
+ _valueGetterFunc(valueGetterFunc),
+ _checkValueTypeFunc(checkValueTypeFunc),
+ _convertToValueTypeFunc(convertToValueTypeFunc) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ NodeRT::Utils::SetHiddenValue(
+ info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(),
+ True());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void HasKey(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ if (info.Length() == 1 && wrapper->_checkKeyTypeFunc(info[0]))
+ {
+ try
+ {
+ K key = wrapper->_convertToKeyTypeFunc(info[0]);
+
+ bool result = wrapper->_instance->HasKey(key);
+
+ info.GetReturnValue().Set(Nan::New<Boolean>(result));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void Remove(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ if (info.Length() == 1 && wrapper->_checkKeyTypeFunc(info[0]))
+ {
+ try
+ {
+ K key = wrapper->_convertToKeyTypeFunc(info[0]);
+
+ wrapper->_instance->Remove(key);
+
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void Insert(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ if (info.Length() == 2 && wrapper->_checkKeyTypeFunc(info[0]) &&
+ wrapper->_checkValueTypeFunc(info[1]))
+ {
+ try
+ {
+ K key = wrapper->_convertToKeyTypeFunc(info[0]);
+ V value = wrapper->_convertToValueTypeFunc(info[1]);
+
+ bool result = wrapper->_instance->Insert(key, value);
+
+ info.GetReturnValue().Set(Nan::New<Boolean>(result));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void First(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ const std::function<Local<Value>(K)> &keyGetter =
+ wrapper->_keyGetterFunc;
+ const std::function<Local<Value>(V)> &valueGetter =
+ wrapper->_valueGetterFunc;
+ info.GetReturnValue().Set(
+ IteratorWrapper<
+ ::Windows::Foundation::Collections::IKeyValuePair<K, V> ^>::
+ CreateIteratorWrapper(
+ wrapper->_instance->First(),
+ [keyGetter, valueGetter](
+ ::Windows::Foundation::Collections::IKeyValuePair<K,
+ V> ^
+ value)
+ {
+ return KeyValuePairWrapper<
+ K, V>::CreateKeyValuePairWrapper(value, keyGetter,
+ valueGetter);
+ }));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void Lookup(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ if (info.Length() == 1 && wrapper->_checkKeyTypeFunc(info[0]))
+ {
+ try
+ {
+ K key = wrapper->_convertToKeyTypeFunc(info[0]);
+
+ V result = wrapper->_instance->Lookup(key);
+
+ info.GetReturnValue().Set(wrapper->_valueGetterFunc(result));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ return;
+ }
+
+ static void GetView(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ ::Windows::Foundation::Collections::IMapView<K, V> ^ result =
+ wrapper->_instance->GetView();
+
+ info.GetReturnValue().Set(MapViewWrapper<K, V>::CreateMapViewWrapper(
+ result, wrapper->_keyGetterFunc, wrapper->_checkKeyTypeFunc,
+ wrapper->_convertToKeyTypeFunc, wrapper->_valueGetterFunc));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void Clear(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ wrapper->_instance->Clear();
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void SizeGetter(Local<String> property,
+ const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+ if (!NodeRT::Utils::IsWinRtWrapperOf<
+ ::Windows::Foundation::Collections::IMap<K, V> ^>(info.This()))
+ {
+ return;
+ }
+
+ MapWrapper<K, V> *wrapper =
+ MapWrapper<K, V>::Unwrap<MapWrapper<K, V>>(info.This());
+
+ try
+ {
+ info.GetReturnValue().Set(Nan::New<Integer>(wrapper->_instance->Size));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Windows::Foundation::Collections::IMap<K, V> ^ _instance;
+
+ std::function<Local<Value>(K)> _keyGetterFunc;
+ std::function<K(Local<Value>)> _convertToKeyTypeFunc;
+ std::function<bool(Local<Value>)> _checkKeyTypeFunc;
+
+ std::function<Local<Value>(V)> _valueGetterFunc;
+ std::function<V(Local<Value>)> _convertToValueTypeFunc;
+ std::function<bool(Local<Value>)> _checkValueTypeFunc;
+
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+ };
+
+ template <class K, class V>
+ Persistent<FunctionTemplate> MapWrapper<K, V>::s_constructorTemplate;
+
+ } // namespace Collections
+}; // namespace NodeRT
diff --git a/desktop/addons/windows-pushnotifications/LICENSE b/desktop/addons/windows-pushnotifications/LICENSE
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/LICENSE
@@ -0,0 +1,194 @@
+Copyright 2019, The NodeRT Contributors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+<http://www.apache.org/licenses/LICENSE-2.0>
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+```
+-------------------------------------------------------------------------
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+```
diff --git a/desktop/addons/windows-pushnotifications/NodeRtUtils.h b/desktop/addons/windows-pushnotifications/NodeRtUtils.h
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/NodeRtUtils.h
@@ -0,0 +1,148 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#pragma once
+
+#include <v8.h>
+#include "nan.h"
+
+#define WCHART_NOT_BUILTIN_IN_NODE 1
+
+namespace NodeRT
+{
+ namespace Utils
+ {
+
+ v8::Local<v8::Value> WinRtExceptionToJsError(Platform::Exception ^ exception);
+
+ void ThrowWinRtExceptionInJs(Platform::Exception ^ exception);
+
+ // creates an object with the following structure:
+ // {
+ // "callback" : [callback function]
+ // "domain" : [the domain in which the async function/event was
+ // called/registered] (this is optional)
+ // }
+ v8::Local<v8::Object> CreateCallbackObjectInDomain(
+ v8::Local<v8::Function> callback);
+
+ // Calls the callback in the appropriate domwin, expects an object in the
+ // following format:
+ // {
+ // "callback" : [callback fuction]
+ // "domain" : [the domain in which the async function/event was
+ // called/registered] (this is optional)
+ // }
+ v8::Local<v8::Value> CallCallbackInDomain(v8::Local<v8::Object> callbackObject,
+ int argc,
+ v8::Local<v8::Value> argv[]);
+
+ v8::Local<v8::String> NewString(const wchar_t *str);
+
+ const wchar_t *StringToWchar(v8::String::Value &str);
+
+ ::Platform::String ^ V8StringToPlatformString(v8::Local<v8::Value> value);
+
+#ifdef WCHART_NOT_BUILTIN_IN_NODE
+ // compares 2 strings using a case insensitive comparison
+ bool CaseInsenstiveEquals(const wchar_t *str1, const uint16_t *str2);
+#endif
+
+ // compares 2 strings using a case insensitive comparison
+ bool CaseInsenstiveEquals(const wchar_t *str1, const wchar_t *str2);
+
+ // registers the namespace & required object on the global object
+ void RegisterNameSpace(const char *ns, v8::Local<v8::Value> nsExports);
+
+ v8::Local<v8::Value> CreateExternalWinRTObject(const char *ns,
+ const char *objectName,
+ ::Platform::Object ^ instance);
+
+ bool IsWinRtWrapper(v8::Local<v8::Value> value);
+
+ template <class T>
+ bool IsWinRtWrapperOf(v8::Local<v8::Value> value)
+ {
+ if (!IsWinRtWrapper(value))
+ {
+ return false;
+ }
+
+ if (value->IsNull())
+ {
+ return true;
+ }
+
+ WrapperBase *wrapper =
+ Nan::ObjectWrap::Unwrap<WrapperBase>(value.As<v8::Object>());
+
+ if (wrapper->GetObjectInstance() == nullptr)
+ {
+ return false;
+ }
+
+ try
+ {
+ T instance = dynamic_cast<T>(wrapper->GetObjectInstance());
+ return (instance != nullptr);
+ }
+ catch (...)
+ {
+ return false;
+ }
+ }
+
+ ::Platform::Object ^ GetObjectInstance(v8::Local<v8::Value> value);
+
+ void SetHiddenValue(v8::Local<v8::Object> obj,
+ v8::Local<v8::String> symbol,
+ v8::Local<v8::Primitive> data);
+ void SetHiddenValueWithObject(v8::Local<v8::Object> obj,
+ v8::Local<v8::String> symbol,
+ v8::Local<v8::Object> data);
+ v8::Local<v8::Value> GetHiddenValue(v8::Local<v8::Object> obj,
+ v8::Local<v8::String> symbol);
+
+ v8::Local<v8::Date> DateTimeToJS(::Windows::Foundation::DateTime value);
+ ::Windows::Foundation::TimeSpan TimeSpanFromMilli(int64_t millis);
+ ::Windows::Foundation::DateTime DateTimeFromJSDate(v8::Local<v8::Value> value);
+
+ bool IsGuid(v8::Local<v8::Value> value);
+ ::Platform::Guid GuidFromJs(v8::Local<v8::Value> value);
+ v8::Local<v8::String> GuidToJs(::Platform::Guid guid);
+
+ v8::Local<v8::Object> ColorToJs(::Windows::UI::Color color);
+ ::Windows::UI::Color ColorFromJs(v8::Local<v8::Value> value);
+ bool IsColor(v8::Local<v8::Value> value);
+
+ v8::Local<v8::Object> RectToJs(::Windows::Foundation::Rect rect);
+ ::Windows::Foundation::Rect RectFromJs(v8::Local<v8::Value> value);
+ bool IsRect(v8::Local<v8::Value> value);
+
+ v8::Local<v8::Object> PointToJs(::Windows::Foundation::Point point);
+ ::Windows::Foundation::Point PointFromJs(v8::Local<v8::Value> value);
+ bool IsPoint(v8::Local<v8::Value> value);
+
+ v8::Local<v8::Object> SizeToJs(::Windows::Foundation::Size size);
+ ::Windows::Foundation::Size SizeFromJs(v8::Local<v8::Value> value);
+ bool IsSize(v8::Local<v8::Value> value);
+
+ wchar_t GetFirstChar(v8::Local<v8::Value> value);
+ v8::Local<v8::String> JsStringFromChar(wchar_t value);
+
+ ::Windows::Foundation::HResult HResultFromJsInt32(int32_t value);
+
+ } // namespace Utils
+} // namespace NodeRT
\ No newline at end of file
diff --git a/desktop/addons/windows-pushnotifications/NodeRtUtils.cpp b/desktop/addons/windows-pushnotifications/NodeRtUtils.cpp
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/NodeRtUtils.cpp
@@ -0,0 +1,809 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#include "NodeRtUtils.h"
+#include <v8.h>
+#include <string>
+#include "OpaqueWrapper.h"
+#include "nan.h"
+
+#define WCHART_NOT_BUILTIN_IN_NODE 1
+
+namespace NodeRT
+{
+ namespace Utils
+ {
+
+ using Nan::EscapableHandleScope;
+ using Nan::False;
+ using Nan::HandleScope;
+ using Nan::MaybeLocal;
+ using Nan::Null;
+ using Nan::Persistent;
+ using Nan::True;
+ using Nan::Undefined;
+ using v8::Boolean;
+ using v8::Date;
+ using v8::Function;
+ using v8::FunctionTemplate;
+ using v8::Integer;
+ using v8::Local;
+ using v8::Number;
+ using v8::Object;
+ using v8::Primitive;
+ using v8::PropertyAttribute;
+ using v8::String;
+ using v8::Value;
+
+ v8::Local<v8::Value> WinRtExceptionToJsError(Platform::Exception ^ exception)
+ {
+ EscapableHandleScope scope;
+
+ if (exception == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ // we use casting here in case that wchar_t is not a built-in type
+ const wchar_t *errorMessage = exception->Message->Data();
+ unsigned int length = exception->Message->Length();
+
+ Local<Value> error = Nan::Error(
+ Nan::New<String>(reinterpret_cast<const uint16_t *>(errorMessage))
+ .ToLocalChecked());
+ Nan::Set(Nan::To<Object>(error).ToLocalChecked(),
+ Nan::New<String>("HRESULT").ToLocalChecked(),
+ Nan::New<Integer>(exception->HResult));
+
+ return scope.Escape(error);
+ }
+
+ void ThrowWinRtExceptionInJs(Platform::Exception ^ exception)
+ {
+ if (exception == nullptr)
+ {
+ return;
+ }
+
+ Nan::ThrowError(WinRtExceptionToJsError(exception));
+ }
+
+ // creates an object with the following structure:
+ // {
+ // "callback" : [callback fuction]
+ // "domain" : [the domain in which the async function/event was
+ // called/registered] (this is optional)
+ // }
+ Local<v8::Object> CreateCallbackObjectInDomain(Local<v8::Function> callback)
+ {
+ EscapableHandleScope scope;
+
+ // get the current domain:
+ MaybeLocal<v8::Object> callbackObject = Nan::New<Object>();
+
+ Nan::Set(callbackObject.ToLocalChecked(),
+ Nan::New<String>("callback").ToLocalChecked(), callback);
+
+ MaybeLocal<Value> processVal =
+ Nan::Get(Nan::GetCurrentContext()->Global(),
+ Nan::New<String>("process").ToLocalChecked());
+ v8::Local<Object> process =
+ Nan::To<Object>(processVal.ToLocalChecked()).ToLocalChecked();
+ if (process.IsEmpty() || Nan::Equals(process, Undefined()).FromMaybe(true))
+ {
+ return scope.Escape(callbackObject.ToLocalChecked());
+ }
+
+ MaybeLocal<Value> currentDomain =
+ Nan::Get(process, Nan::New<String>("domain").ToLocalChecked());
+
+ if (!currentDomain.IsEmpty() &&
+ !Nan::Equals(currentDomain.ToLocalChecked(), Undefined())
+ .FromMaybe(true))
+ {
+ Nan::Set(callbackObject.ToLocalChecked(),
+ Nan::New<String>("domain").ToLocalChecked(),
+ currentDomain.ToLocalChecked());
+ }
+
+ return scope.Escape(callbackObject.ToLocalChecked());
+ }
+
+ // Calls the callback in the appropriate domwin, expects an object in the
+ // following format:
+ // {
+ // "callback" : [callback function]
+ // "domain" : [the domain in which the async function/event was
+ // called/registered] (this is optional)
+ // }
+ Local<Value> CallCallbackInDomain(Local<v8::Object> callbackObject,
+ int argc,
+ Local<Value> argv[])
+ {
+ Nan::AsyncResource asyncResource(Nan::New<String>("CallCallbackInDomain").ToLocalChecked());
+ return asyncResource.runInAsyncScope(
+ callbackObject,
+ Nan::New<String>("callback").ToLocalChecked(), argc,
+ argv)
+ .FromMaybe(v8::Local<v8::Value>());
+ }
+
+ ::Platform::Object ^
+ GetObjectInstance(Local<Value> value) {
+ // nulls are allowed when a WinRT wrapped object is expected
+ if (value->IsNull())
+ {
+ return nullptr;
+ }
+
+ WrapperBase *wrapper = Nan::ObjectWrap::Unwrap<WrapperBase>(
+ Nan::To<Object>(value).ToLocalChecked());
+ return wrapper->GetObjectInstance();
+ }
+
+ Local<String> NewString(const wchar_t *str)
+ {
+#ifdef WCHART_NOT_BUILTIN_IN_NODE
+ return Nan::New<String>(reinterpret_cast<const uint16_t *>(str))
+ .ToLocalChecked();
+#else
+ return Nan::New<String>(str).ToLocalChecked();
+#endif
+ }
+
+ const wchar_t *StringToWchar(v8::String::Value &str)
+ {
+#ifdef WCHART_NOT_BUILTIN_IN_NODE
+ return reinterpret_cast<const wchar_t *>(*str);
+#else
+ return *str;
+#endif
+ }
+
+ // Note: current implementation converts any JS value that has a toString method
+ // to a ::Platform::String^ Changes to this code might break the Collection
+ // Convertor logic
+ ::Platform::String ^
+ V8StringToPlatformString(Local<Value> value) {
+ v8::String::Value stringVal(v8::Isolate::GetCurrent(), value);
+#ifdef WCHART_NOT_BUILTIN_IN_NODE
+ return ref new Platform::String(
+ reinterpret_cast<const wchar_t *>(*stringVal));
+#else
+ return ref new Platform::String(*stringVal);
+#endif
+ }
+
+#ifndef min
+ size_t min(size_t one, size_t two)
+ {
+ if (one < two)
+ {
+ return one;
+ }
+
+ return two;
+ }
+#endif
+
+#ifdef WCHART_NOT_BUILTIN_IN_NODE
+ // compares 2 strings using a case insensitive comparison
+ bool CaseInsenstiveEquals(const wchar_t *str1, const uint16_t *str2)
+ {
+ int maxCount = static_cast<int>(
+ min(wcslen(str1), wcslen(reinterpret_cast<const wchar_t *>(str2))));
+ return (_wcsnicmp(str1, reinterpret_cast<const wchar_t *>(str2), maxCount) ==
+ 0);
+ }
+#endif
+
+ // compares 2 strings using a case insensitive comparison
+ bool CaseInsenstiveEquals(const wchar_t *str1, const wchar_t *str2)
+ {
+ int maxCount = static_cast<int>(min(wcslen(str1), wcslen(str2)));
+ return (_wcsnicmp(str1, str2, maxCount) == 0);
+ }
+
+ void RegisterNameSpace(const char *ns, Local<Value> nsExports)
+ {
+ HandleScope scope;
+ Local<Object> global = Nan::GetCurrentContext()->Global();
+
+ if (!Nan::Has(global,
+ Nan::New<String>("__winRtNamespaces__").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ Nan::ForceSet(global,
+ Nan::New<String>("__winRtNamespaces__").ToLocalChecked(),
+ Nan::New<Object>(),
+ (v8::PropertyAttribute)(v8::PropertyAttribute::DontEnum &
+ v8::PropertyAttribute::DontDelete));
+ }
+
+ MaybeLocal<Value> nsObject = Nan::Get(
+ global, Nan::New<String>("__winRtNamespaces__").ToLocalChecked());
+ Nan::Set(Nan::To<Object>(nsObject.ToLocalChecked()).ToLocalChecked(),
+ Nan::New<String>(ns).ToLocalChecked(), nsExports);
+ }
+
+ Local<Value> CreateExternalWinRTObject(const char *ns,
+ const char *objectName,
+ ::Platform::Object ^ instance)
+ {
+ EscapableHandleScope scope;
+ Local<Value> opaqueWrapper = CreateOpaqueWrapper(instance);
+
+ Local<Object> global = Nan::GetCurrentContext()->Global();
+ if (!Nan::Has(global,
+ Nan::New<String>("__winRtNamespaces__").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ return scope.Escape(opaqueWrapper);
+ }
+
+ Local<Object> winRtObj =
+ Nan::To<Object>(
+ Nan::Get(global,
+ Nan::New<String>("__winRtNamespaces__").ToLocalChecked())
+ .ToLocalChecked())
+ .ToLocalChecked();
+
+ Local<String> nsSymbol = Nan::New<String>(ns).ToLocalChecked();
+ if (!Nan::Has(winRtObj, nsSymbol).FromMaybe(false))
+ {
+ return scope.Escape(opaqueWrapper);
+ }
+
+ v8::MaybeLocal<Value> maybeLocalRef = Nan::Get(winRtObj, nsSymbol);
+
+ if (maybeLocalRef.IsEmpty())
+ {
+ return scope.Escape(opaqueWrapper);
+ }
+
+ Local<Value> nsObjectValue = maybeLocalRef.ToLocalChecked();
+
+ if (Nan::Equals(nsObjectValue, Undefined()).FromMaybe(false))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(
+ L"Failed to obtain external namespace object")));
+ return Undefined();
+ }
+
+ Local<Object> nsObject = Nan::To<Object>(nsObjectValue).ToLocalChecked();
+
+ Local<String> objectNameSymbol =
+ Nan::New<String>(objectName).ToLocalChecked();
+ if (!Nan::Has(nsObject, objectNameSymbol).FromMaybe(false))
+ {
+ return scope.Escape(opaqueWrapper);
+ }
+
+ Local<Function> objectFunc =
+ Nan::Get(nsObject, objectNameSymbol).ToLocalChecked().As<Function>();
+ Local<Value> args[] = {opaqueWrapper};
+ return scope.Escape(
+ Nan::NewInstance(objectFunc, _countof(args), args).ToLocalChecked());
+ }
+
+ bool IsWinRtWrapper(Local<Value> value)
+ {
+ if (value.IsEmpty() || (!value->IsObject() && !value->IsNull()))
+ {
+ return false;
+ }
+
+ // allow passing nulls when a WinRT wrapped object is expected
+ if (value->IsNull())
+ {
+ return true;
+ }
+
+ if (NodeRT::OpaqueWrapper::IsOpaqueWrapper(value))
+ {
+ return true;
+ }
+
+ Local<Value> hiddenVal =
+ GetHiddenValue(Nan::To<Object>(value).ToLocalChecked(),
+ Nan::New<String>("__winRtInstance__").ToLocalChecked());
+
+ return (!hiddenVal.IsEmpty() && hiddenVal->IsTrue());
+ }
+
+ void SetHiddenValue(Local<Object> obj,
+ Local<String> symbol,
+ Local<Primitive> data)
+ {
+ Nan::ForceSet(obj, symbol, data,
+ static_cast<PropertyAttribute>(v8::ReadOnly & v8::DontEnum));
+ }
+
+ void SetHiddenValueWithObject(Local<Object> obj,
+ Local<String> symbol,
+ Local<Object> data)
+ {
+ Nan::ForceSet(obj, symbol, data,
+ static_cast<PropertyAttribute>(v8::ReadOnly & v8::DontEnum));
+ }
+
+ Local<Value> GetHiddenValue(Local<Object> obj, Local<String> symbol)
+ {
+ return Nan::Get(obj, symbol).ToLocalChecked();
+ }
+
+ ::Windows::Foundation::TimeSpan TimeSpanFromMilli(int64_t millis)
+ {
+ ::Windows::Foundation::TimeSpan timeSpan;
+ timeSpan.Duration = millis * 10000;
+
+ return timeSpan;
+ }
+
+ ::Windows::Foundation::DateTime DateTimeFromJSDate(Local<Value> value)
+ {
+ ::Windows::Foundation::DateTime time;
+ time.UniversalTime = 0;
+ if (value->IsDate())
+ {
+ // 116444736000000000 = The time in 100 nanoseconds between 1/1/1970(UTC) to
+ // 1/1/1601(UTC) ux_time = (Current time since 1601 in 100 nano sec
+ // units)/10000 - 116444736000000000;
+ time.UniversalTime = value->IntegerValue(Nan::GetCurrentContext()).FromMaybe(0) * 10000 + 116444736000000000;
+ }
+
+ return time;
+ }
+
+ Local<Date> DateTimeToJS(::Windows::Foundation::DateTime value)
+ {
+ // 116444736000000000 = The time 100 nanoseconds between 1/1/1970(UTC) to
+ // 1/1/1601(UTC) ux_time = (Current time since 1601 in 100 nano sec
+ // units)/10000 - 11644473600000;
+ return Nan::New<Date>(value.UniversalTime / 10000.0 - 11644473600000)
+ .ToLocalChecked();
+ }
+
+ bool StrToGuid(Local<Value> value, LPCLSID guid)
+ {
+ if (value.IsEmpty() || !value->IsString())
+ {
+ return false;
+ }
+
+ v8::String::Value stringVal(v8::Isolate::GetCurrent(), value);
+ std::wstring guidStr(L"{");
+ guidStr += StringToWchar(stringVal);
+ guidStr += L"}";
+
+ HRESULT hr = CLSIDFromString(guidStr.c_str(), guid);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool IsGuid(Local<Value> value)
+ {
+ GUID guid;
+ return StrToGuid(value, &guid);
+ }
+
+ ::Platform::Guid GuidFromJs(Local<Value> value)
+ {
+ GUID guid;
+ if (!StrToGuid(value, &guid))
+ {
+ return ::Platform::Guid();
+ }
+
+ return ::Platform::Guid(guid);
+ }
+
+ Local<String> GuidToJs(::Platform::Guid guid)
+ {
+ OLECHAR *bstrGuid;
+ StringFromCLSID(guid, &bstrGuid);
+
+ Local<String> strVal = NewString(bstrGuid);
+ CoTaskMemFree(bstrGuid);
+ return strVal;
+ }
+
+ Local<Object> ColorToJs(::Windows::UI::Color color)
+ {
+ EscapableHandleScope scope;
+ Local<Object> obj = Nan::New<Object>();
+
+ Nan::Set(obj, Nan::New<String>("G").ToLocalChecked(),
+ Nan::New<Integer>(color.G));
+ Nan::Set(obj, Nan::New<String>("B").ToLocalChecked(),
+ Nan::New<Integer>(color.B));
+ Nan::Set(obj, Nan::New<String>("A").ToLocalChecked(),
+ Nan::New<Integer>(color.A));
+ Nan::Set(obj, Nan::New<String>("R").ToLocalChecked(),
+ Nan::New<Integer>(color.R));
+
+ return scope.Escape(obj);
+ }
+
+ ::Windows::UI::Color ColorFromJs(Local<Value> value)
+ {
+ ::Windows::UI::Color retVal = ::Windows::UI::Colors::Black;
+ if (!value->IsObject())
+ {
+ Nan::ThrowError(Nan::Error(
+ NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
+ return retVal;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+ if (!Nan::Has(obj, Nan::New<String>("G").ToLocalChecked()).FromMaybe(false))
+ {
+ retVal.G = static_cast<unsigned char>(
+ Nan::To<uint32_t>(Nan::Get(obj, Nan::New<String>("G").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0));
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("A").ToLocalChecked()).FromMaybe(false))
+ {
+ retVal.G = static_cast<unsigned char>(
+ Nan::To<uint32_t>(Nan::Get(obj, Nan::New<String>("A").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0));
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("B").ToLocalChecked()).FromMaybe(false))
+ {
+ retVal.G = static_cast<unsigned char>(
+ Nan::To<uint32_t>(Nan::Get(obj, Nan::New<String>("B").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0));
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("R").ToLocalChecked()).FromMaybe(false))
+ {
+ retVal.G = static_cast<unsigned char>(
+ Nan::To<uint32_t>(Nan::Get(obj, Nan::New<String>("R").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0));
+ }
+
+ return retVal;
+ }
+
+ bool IsColor(Local<Value> value)
+ {
+ if (!value->IsObject())
+ {
+ return false;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+ if (!Nan::Has(obj, Nan::New<String>("G").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("A").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("B").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("R").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ Local<Object> RectToJs(::Windows::Foundation::Rect rect)
+ {
+ EscapableHandleScope scope;
+ Local<Object> obj = Nan::New<Object>();
+
+ Nan::Set(obj, Nan::New<String>("bottom").ToLocalChecked(),
+ Nan::New<Number>(rect.Bottom));
+ Nan::Set(obj, Nan::New<String>("height").ToLocalChecked(),
+ Nan::New<Number>(rect.Height));
+ Nan::Set(obj, Nan::New<String>("left").ToLocalChecked(),
+ Nan::New<Number>(rect.Left));
+ Nan::Set(obj, Nan::New<String>("right").ToLocalChecked(),
+ Nan::New<Number>(rect.Right));
+ Nan::Set(obj, Nan::New<String>("top").ToLocalChecked(),
+ Nan::New<Number>(rect.Top));
+ Nan::Set(obj, Nan::New<String>("width").ToLocalChecked(),
+ Nan::New<Number>(rect.Width));
+ Nan::Set(obj, Nan::New<String>("x").ToLocalChecked(),
+ Nan::New<Number>(rect.X));
+ Nan::Set(obj, Nan::New<String>("y").ToLocalChecked(),
+ Nan::New<Number>(rect.Y));
+
+ return scope.Escape(obj);
+ }
+
+ ::Windows::Foundation::Rect RectFromJs(Local<Value> value)
+ {
+ ::Windows::Foundation::Rect rect = ::Windows::Foundation::Rect::Empty;
+
+ if (!value->IsObject())
+ {
+ Nan::ThrowError(Nan::Error(
+ NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
+ return rect;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ if (Nan::Has(obj, Nan::New<String>("x").ToLocalChecked()).FromMaybe(false))
+ {
+ rect.X = static_cast<float>(
+ Nan::To<double>(Nan::Get(obj, Nan::New<String>("x").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ if (Nan::Has(obj, Nan::New<String>("y").ToLocalChecked()).FromMaybe(false))
+ {
+ rect.Y = static_cast<float>(
+ Nan::To<double>(Nan::Get(obj, Nan::New<String>("y").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ if (Nan::Has(obj, Nan::New<String>("height").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ rect.Height = static_cast<float>(
+ Nan::To<double>(
+ Nan::Get(obj, Nan::New<String>("height").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ if (Nan::Has(obj, Nan::New<String>("width").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ rect.Width = static_cast<float>(
+ Nan::To<double>(
+ Nan::Get(obj, Nan::New<String>("width").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ return rect;
+ }
+
+ bool IsRect(Local<Value> value)
+ {
+ if (!value->IsObject())
+ {
+ return false;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ if (!Nan::Has(obj, Nan::New<String>("x").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("y").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("height").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("width").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ Local<Object> PointToJs(::Windows::Foundation::Point point)
+ {
+ EscapableHandleScope scope;
+ Local<Object> obj = Nan::New<Object>();
+
+ Nan::Set(obj, Nan::New<String>("x").ToLocalChecked(),
+ Nan::New<Number>(point.X));
+ Nan::Set(obj, Nan::New<String>("y").ToLocalChecked(),
+ Nan::New<Number>(point.Y));
+
+ return scope.Escape(obj);
+ }
+
+ ::Windows::Foundation::Point PointFromJs(Local<Value> value)
+ {
+ ::Windows::Foundation::Point point(0, 0);
+
+ if (!value->IsObject())
+ {
+ Nan::ThrowError(Nan::Error(
+ NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
+ return point;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ if (Nan::Has(obj, Nan::New<String>("x").ToLocalChecked()).FromMaybe(false))
+ {
+ point.X = static_cast<float>(
+ Nan::To<double>(Nan::Get(obj, Nan::New<String>("x").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ if (Nan::Has(obj, Nan::New<String>("y").ToLocalChecked()).FromMaybe(false))
+ {
+ point.Y = static_cast<float>(
+ Nan::To<double>(Nan::Get(obj, Nan::New<String>("y").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ return point;
+ }
+
+ bool IsPoint(Local<Value> value)
+ {
+ if (!value->IsObject())
+ {
+ return false;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ if (!Nan::Has(obj, Nan::New<String>("x").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("y").ToLocalChecked()).FromMaybe(false))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ Local<Object> SizeToJs(::Windows::Foundation::Size size)
+ {
+ EscapableHandleScope scope;
+ Local<Object> obj = Nan::New<Object>();
+
+ Nan::Set(obj, Nan::New<String>("height").ToLocalChecked(),
+ Nan::New<Number>(size.Height));
+ Nan::Set(obj, Nan::New<String>("width").ToLocalChecked(),
+ Nan::New<Number>(size.Width));
+
+ return scope.Escape(obj);
+ }
+
+ ::Windows::Foundation::Size SizeFromJs(Local<Value> value)
+ {
+ ::Windows::Foundation::Size size(0, 0);
+
+ if (!value->IsObject())
+ {
+ Nan::ThrowError(Nan::Error(
+ NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
+ return size;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ if (Nan::Has(obj, Nan::New<String>("height").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ size.Height = static_cast<float>(
+ Nan::To<double>(
+ Nan::Get(obj, Nan::New<String>("height").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ if (Nan::Has(obj, Nan::New<String>("width").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ size.Width = static_cast<float>(
+ Nan::To<double>(
+ Nan::Get(obj, Nan::New<String>("width").ToLocalChecked())
+ .ToLocalChecked())
+ .FromMaybe(0.0));
+ }
+
+ return size;
+ }
+
+ bool IsSize(Local<Value> value)
+ {
+ if (!value->IsObject())
+ {
+ return false;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ if (!Nan::Has(obj, Nan::New<String>("height").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ return false;
+ }
+
+ if (!Nan::Has(obj, Nan::New<String>("width").ToLocalChecked())
+ .FromMaybe(false))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ wchar_t GetFirstChar(Local<Value> value)
+ {
+ wchar_t retVal = 0;
+
+ if (!value->IsString())
+ {
+ return retVal;
+ }
+
+ Local<String> str = Nan::To<String>(value).ToLocalChecked();
+ if (str->Length() == 0)
+ {
+ return retVal;
+ }
+
+ String::Value val(v8::Isolate::GetCurrent(), str);
+ retVal = (*val)[0];
+ return retVal;
+ }
+
+ Local<String> JsStringFromChar(wchar_t value)
+ {
+ wchar_t str[2];
+ str[0] = value;
+ str[1] = L'\0';
+
+ return NewString(str);
+ }
+
+ ::Windows::Foundation::HResult HResultFromJsInt32(int32_t value)
+ {
+ ::Windows::Foundation::HResult res;
+ res.Value = value;
+ return res;
+ }
+
+ } // namespace Utils
+} // namespace NodeRT
diff --git a/desktop/addons/windows-pushnotifications/OpaqueWrapper.h b/desktop/addons/windows-pushnotifications/OpaqueWrapper.h
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/OpaqueWrapper.h
@@ -0,0 +1,73 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#pragma once
+
+#include <node.h>
+#include <v8.h>
+#include <string>
+#include "NodeRTUtils.h"
+#include "WrapperBase.h"
+#include "nan.h"
+#include "nan_object_wrap.h"
+
+namespace NodeRT
+{
+ class OpaqueWrapperInitializer;
+
+ v8::Local<v8::Value> CreateOpaqueWrapper(::Platform::Object ^ wintRtHandle);
+
+ class OpaqueWrapper : public WrapperBase
+ {
+ public:
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ static bool IsOpaqueWrapper(v8::Local<v8::Value> value)
+ {
+ if (value.IsEmpty() || !value->IsObject())
+ {
+ return false;
+ }
+
+ v8::Local<v8::Value> hiddenVal = NodeRT::Utils::GetHiddenValue(
+ value.As<v8::Object>(),
+ Nan::New<v8::String>("__winrtOpaqueWrapper__").ToLocalChecked());
+
+ if (hiddenVal.IsEmpty() || !hiddenVal->IsBoolean())
+ {
+ return false;
+ }
+
+ return hiddenVal->IsTrue();
+ }
+
+ private:
+ OpaqueWrapper(::Platform::Object ^ instance) : _instance(instance) {}
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info);
+ static void Init();
+
+ private:
+ ::Platform::Object ^ _instance;
+ static Nan::Persistent<v8::FunctionTemplate> s_constructorTemplate;
+
+ friend OpaqueWrapperInitializer;
+ friend v8::Local<v8::Value> CreateOpaqueWrapper(::Platform::Object ^
+ wintRtInstance);
+ };
+} // namespace NodeRT
diff --git a/desktop/addons/windows-pushnotifications/OpaqueWrapper.cpp b/desktop/addons/windows-pushnotifications/OpaqueWrapper.cpp
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/OpaqueWrapper.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing permissions
+// and limitations under the License.
+
+#include "OpaqueWrapper.h"
+#include "NodeRtUtils.h"
+
+using v8::FunctionTemplate;
+using v8::String;
+
+Nan::Persistent<v8::FunctionTemplate> NodeRT::OpaqueWrapper::s_constructorTemplate;
+
+void NodeRT::OpaqueWrapper::New(Nan::NAN_METHOD_ARGS_TYPE info)
+{
+ NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winrtOpaqueWrapper__").ToLocalChecked(), Nan::True());
+
+ info.GetReturnValue().Set(info.This());
+}
+
+void NodeRT::OpaqueWrapper::Init()
+{
+ Nan::HandleScope scope;
+ // Prepare constructor template
+ s_constructorTemplate.Reset(Nan::New<FunctionTemplate>(New));
+ v8::Local<v8::FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);
+ localRef->SetClassName(Nan::New<String>("OpaqueWrapper").ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+}
+
+namespace NodeRT
+{
+ v8::Local<v8::Value> CreateOpaqueWrapper(::Platform::Object ^ winRtInstance)
+ {
+ Nan::EscapableHandleScope scope;
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Nan::Undefined());
+ }
+
+ v8::Local<v8::Value> args[] = {Nan::Undefined()};
+ if (OpaqueWrapper::s_constructorTemplate.IsEmpty())
+ {
+ OpaqueWrapper::Init();
+ }
+
+ v8::Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(OpaqueWrapper::s_constructorTemplate);
+ v8::Local<v8::Object> objectInstance = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), 0, args).ToLocalChecked();
+ if (objectInstance.IsEmpty())
+ {
+ return scope.Escape(Nan::Undefined());
+ }
+ OpaqueWrapper *wrapperInstance = new OpaqueWrapper(winRtInstance);
+ wrapperInstance->Wrap(objectInstance);
+ return scope.Escape(objectInstance);
+ }
+}
diff --git a/desktop/addons/windows-pushnotifications/WrapperBase.h b/desktop/addons/windows-pushnotifications/WrapperBase.h
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/WrapperBase.h
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#pragma once
+#include <nan_object_wrap.h>
+
+namespace NodeRT
+{
+ class WrapperBase : public Nan::ObjectWrap
+ {
+ public:
+ virtual ::Platform::Object ^ GetObjectInstance() const = 0;
+ };
+} // namespace NodeRT
\ No newline at end of file
diff --git a/desktop/addons/windows-pushnotifications/_nodert_generated.cpp b/desktop/addons/windows-pushnotifications/_nodert_generated.cpp
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/_nodert_generated.cpp
@@ -0,0 +1,1662 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing permissions
+// and limitations under the License.
+
+// TODO: Verify that this is is still needed..
+#define NTDDI_VERSION 0x06010000
+
+#include <v8.h>
+#include "nan.h"
+#include <string>
+#include <ppltasks.h>
+#include "CollectionsConverter.h"
+#include "CollectionsWrap.h"
+#include "node-async.h"
+#include "NodeRtUtils.h"
+#include "OpaqueWrapper.h"
+#include "WrapperBase.h"
+
+#using < Microsoft.Windows.PushNotifications.WinMD>
+
+// this undefs fixes the issues of compiling Windows.Data.Json, Windows.Storag.FileProperties, and Windows.Stroage.Search
+// Some of the node header files brings windows definitions with the same names as some of the WinRT methods
+#undef DocumentProperties
+#undef GetObject
+#undef CreateEvent
+#undef FindText
+#undef SendMessage
+
+const char *REGISTRATION_TOKEN_MAP_PROPERTY_NAME = "__registrationTokenMap__";
+
+using Nan::EscapableHandleScope;
+using Nan::False;
+using Nan::HandleScope;
+using Nan::MaybeLocal;
+using Nan::Null;
+using Nan::Persistent;
+using Nan::True;
+using Nan::TryCatch;
+using Nan::Undefined;
+using v8::Array;
+using v8::Boolean;
+using v8::Date;
+using v8::Function;
+using v8::FunctionTemplate;
+using v8::Integer;
+using v8::Local;
+using v8::Number;
+using v8::Object;
+using v8::Primitive;
+using v8::PropertyAttribute;
+using v8::String;
+using v8::Value;
+using namespace concurrency;
+
+namespace NodeRT
+{
+ namespace Microsoft
+ {
+ namespace Windows
+ {
+ namespace PushNotifications
+ {
+ v8::Local<v8::Value> WrapPushNotificationChannel(::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ wintRtInstance);
+ ::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ UnwrapPushNotificationChannel(Local<Value> value);
+
+ v8::Local<v8::Value> WrapPushNotificationCreateChannelResult(::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ wintRtInstance);
+ ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ UnwrapPushNotificationCreateChannelResult(Local<Value> value);
+
+ v8::Local<v8::Value> WrapPushNotificationManager(::Microsoft::Windows::PushNotifications::PushNotificationManager ^ wintRtInstance);
+ ::Microsoft::Windows::PushNotifications::PushNotificationManager ^ UnwrapPushNotificationManager(Local<Value> value);
+
+ v8::Local<v8::Value> WrapPushNotificationReceivedEventArgs(::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ wintRtInstance);
+ ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ UnwrapPushNotificationReceivedEventArgs(Local<Value> value);
+
+ static void InitPushNotificationChannelStatusEnum(const Local<Object> exports)
+ {
+ HandleScope scope;
+
+ Local<Object> enumObject = Nan::New<Object>();
+
+ Nan::Set(exports, Nan::New<String>("PushNotificationChannelStatus").ToLocalChecked(), enumObject);
+ Nan::Set(enumObject, Nan::New<String>("inProgress").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Microsoft::Windows::PushNotifications::PushNotificationChannelStatus::InProgress)));
+ Nan::Set(enumObject, Nan::New<String>("inProgressRetry").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Microsoft::Windows::PushNotifications::PushNotificationChannelStatus::InProgressRetry)));
+ Nan::Set(enumObject, Nan::New<String>("completedSuccess").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Microsoft::Windows::PushNotifications::PushNotificationChannelStatus::CompletedSuccess)));
+ Nan::Set(enumObject, Nan::New<String>("completedFailure").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Microsoft::Windows::PushNotifications::PushNotificationChannelStatus::CompletedFailure)));
+ }
+
+ static bool IsPushNotificationCreateChannelStatusJsObject(Local<Value> value)
+ {
+ if (!value->IsObject())
+ {
+ return false;
+ }
+
+ Local<String> symbol;
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ symbol = Nan::New<String>("status").ToLocalChecked();
+ if (Nan::Has(obj, symbol).FromMaybe(false))
+ {
+ if (!Nan::Get(obj, symbol).ToLocalChecked()->IsInt32())
+ {
+ return false;
+ }
+ }
+
+ symbol = Nan::New<String>("extendedError").ToLocalChecked();
+ if (Nan::Has(obj, symbol).FromMaybe(false))
+ {
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Platform::Exception ^>(Nan::Get(obj, symbol).ToLocalChecked()))
+ {
+ return false;
+ }
+ }
+
+ symbol = Nan::New<String>("retryCount").ToLocalChecked();
+ if (Nan::Has(obj, symbol).FromMaybe(false))
+ {
+ if (!Nan::Get(obj, symbol).ToLocalChecked()->IsUint32())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelStatus PushNotificationCreateChannelStatusFromJsObject(Local<Value> value)
+ {
+ HandleScope scope;
+ ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelStatus returnValue;
+
+ if (!value->IsObject())
+ {
+ Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
+ return returnValue;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+ Local<String> symbol;
+
+ symbol = Nan::New<String>("status").ToLocalChecked();
+ if (Nan::Has(obj, symbol).FromMaybe(false))
+ {
+ returnValue.status = static_cast<::Microsoft::Windows::PushNotifications::PushNotificationChannelStatus>(Nan::To<int32_t>(Nan::Get(obj, symbol).ToLocalChecked()).FromMaybe(0));
+ }
+
+ symbol = Nan::New<String>("extendedError").ToLocalChecked();
+ if (Nan::Has(obj, symbol).FromMaybe(false))
+ {
+ returnValue.extendedError = NodeRT::Utils::HResultFromJsInt32(Nan::To<int32_t>(Nan::Get(obj, symbol).ToLocalChecked()).FromMaybe(0));
+ }
+
+ symbol = Nan::New<String>("retryCount").ToLocalChecked();
+ if (Nan::Has(obj, symbol).FromMaybe(false))
+ {
+ returnValue.retryCount = static_cast<unsigned int>(Nan::To<uint32_t>(Nan::Get(obj, symbol).ToLocalChecked()).FromMaybe(0));
+ }
+
+ return returnValue;
+ }
+
+ Local<Value> PushNotificationCreateChannelStatusToJsObject(::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelStatus value)
+ {
+ EscapableHandleScope scope;
+
+ Local<Object> obj = Nan::New<Object>();
+
+ Nan::Set(obj, Nan::New<String>("status").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.status)));
+ Nan::Set(obj, Nan::New<String>("extendedError").ToLocalChecked(), Nan::New<Integer>(value.extendedError.Value));
+ Nan::Set(obj, Nan::New<String>("retryCount").ToLocalChecked(), Nan::New<Integer>(value.retryCount));
+
+ return scope.Escape(obj);
+ }
+ static bool IsPushNotificationsContractJsObject(Local<Value> value)
+ {
+ if (!value->IsObject())
+ {
+ return false;
+ }
+
+ Local<String> symbol;
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+
+ return true;
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationsContract PushNotificationsContractFromJsObject(Local<Value> value)
+ {
+ HandleScope scope;
+ ::Microsoft::Windows::PushNotifications::PushNotificationsContract returnValue;
+
+ if (!value->IsObject())
+ {
+ Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
+ return returnValue;
+ }
+
+ Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
+ Local<String> symbol;
+
+ return returnValue;
+ }
+
+ Local<Value> PushNotificationsContractToJsObject(::Microsoft::Windows::PushNotifications::PushNotificationsContract value)
+ {
+ EscapableHandleScope scope;
+
+ Local<Object> obj = Nan::New<Object>();
+
+ return scope.Escape(obj);
+ }
+
+ class PushNotificationChannel : public WrapperBase
+ {
+ public:
+ static void Init(const Local<Object> exports)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(Nan::New<String>("PushNotificationChannel").ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetPrototypeMethod(localRef, "close", Close);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("expirationTime").ToLocalChecked(), ExpirationTimeGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("uri").ToLocalChecked(), UriGetter);
+
+ Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
+ Nan::SetMethod(constructor, "castFrom", CastFrom);
+
+ Nan::Set(exports, Nan::New<String>("PushNotificationChannel").ToLocalChecked(), constructor);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ PushNotificationChannel(::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ instance)
+ {
+ _instance = instance;
+ }
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);
+
+ // in case the constructor was called without the new operator
+ if (!localRef->HasInstance(info.This()))
+ {
+ if (info.Length() > 0)
+ {
+ std::unique_ptr<Local<Value>[]> constructorArgs(new Local<Value>[info.Length()]);
+
+ Local<Value> *argsPtr = constructorArgs.get();
+ for (int i = 0; i < info.Length(); i++)
+ {
+ argsPtr[i] = info[i];
+ }
+
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ else
+ {
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);
+
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ winRtInstance;
+
+ if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
+ NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationChannel ^>(info[0]))
+ {
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationChannel ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
+ return;
+ }
+
+ NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());
+
+ PushNotificationChannel *wrapperInstance = new PushNotificationChannel(winRtInstance);
+ wrapperInstance->Wrap(info.This());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+ if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationChannel ^>(info[0]))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
+ return;
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ winRtInstance;
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationChannel ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+
+ info.GetReturnValue().Set(WrapPushNotificationChannel(winRtInstance));
+ }
+
+ static void Close(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationChannel ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationChannel *wrapper = PushNotificationChannel::Unwrap<PushNotificationChannel>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ wrapper->_instance->Close();
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void ExpirationTimeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationChannel ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationChannel *wrapper = PushNotificationChannel::Unwrap<PushNotificationChannel>(info.This());
+
+ try
+ {
+ ::Windows::Foundation::DateTime result = wrapper->_instance->ExpirationTime;
+ info.GetReturnValue().Set(NodeRT::Utils::DateTimeToJS(result));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void UriGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationChannel ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationChannel *wrapper = PushNotificationChannel::Unwrap<PushNotificationChannel>(info.This());
+
+ try
+ {
+ ::Windows::Foundation::Uri ^ result = wrapper->_instance->Uri;
+ info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Foundation", "Uri", result));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ _instance;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+
+ friend v8::Local<v8::Value> WrapPushNotificationChannel(::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ wintRtInstance);
+ friend ::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ UnwrapPushNotificationChannel(Local<Value> value);
+ };
+
+ Persistent<FunctionTemplate> PushNotificationChannel::s_constructorTemplate;
+
+ v8::Local<v8::Value> WrapPushNotificationChannel(::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ winRtInstance)
+ {
+ EscapableHandleScope scope;
+
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
+ Local<Value> args[] = {opaqueWrapper};
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(PushNotificationChannel::s_constructorTemplate);
+ return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), _countof(args), args).ToLocalChecked());
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ UnwrapPushNotificationChannel(Local<Value> value) {
+ return PushNotificationChannel::Unwrap<PushNotificationChannel>(Nan::To<Object>(value).ToLocalChecked())->_instance;
+ }
+
+ void InitPushNotificationChannel(Local<Object> exports)
+ {
+ PushNotificationChannel::Init(exports);
+ }
+
+ class PushNotificationCreateChannelResult : public WrapperBase
+ {
+ public:
+ static void Init(const Local<Object> exports)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(Nan::New<String>("PushNotificationCreateChannelResult").ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("channel").ToLocalChecked(), ChannelGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("extendedError").ToLocalChecked(), ExtendedErrorGetter);
+ Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("status").ToLocalChecked(), StatusGetter);
+
+ Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
+ Nan::SetMethod(constructor, "castFrom", CastFrom);
+
+ Nan::Set(exports, Nan::New<String>("PushNotificationCreateChannelResult").ToLocalChecked(), constructor);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ PushNotificationCreateChannelResult(::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ instance)
+ {
+ _instance = instance;
+ }
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);
+
+ // in case the constructor was called without the new operator
+ if (!localRef->HasInstance(info.This()))
+ {
+ if (info.Length() > 0)
+ {
+ std::unique_ptr<Local<Value>[]> constructorArgs(new Local<Value>[info.Length()]);
+
+ Local<Value> *argsPtr = constructorArgs.get();
+ for (int i = 0; i < info.Length(); i++)
+ {
+ argsPtr[i] = info[i];
+ }
+
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ else
+ {
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);
+
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ winRtInstance;
+
+ if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
+ NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^>(info[0]))
+ {
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
+ return;
+ }
+
+ NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());
+
+ PushNotificationCreateChannelResult *wrapperInstance = new PushNotificationCreateChannelResult(winRtInstance);
+ wrapperInstance->Wrap(info.This());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+ if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^>(info[0]))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
+ return;
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ winRtInstance;
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+
+ info.GetReturnValue().Set(WrapPushNotificationCreateChannelResult(winRtInstance));
+ }
+
+ static void ChannelGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationCreateChannelResult *wrapper = PushNotificationCreateChannelResult::Unwrap<PushNotificationCreateChannelResult>(info.This());
+
+ try
+ {
+ ::Microsoft::Windows::PushNotifications::PushNotificationChannel ^ result = wrapper->_instance->Channel;
+ info.GetReturnValue().Set(WrapPushNotificationChannel(result));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void ExtendedErrorGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationCreateChannelResult *wrapper = PushNotificationCreateChannelResult::Unwrap<PushNotificationCreateChannelResult>(info.This());
+
+ try
+ {
+ ::Windows::Foundation::HResult result = wrapper->_instance->ExtendedError;
+ info.GetReturnValue().Set(Nan::New<Integer>(result.Value));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void StatusGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationCreateChannelResult *wrapper = PushNotificationCreateChannelResult::Unwrap<PushNotificationCreateChannelResult>(info.This());
+
+ try
+ {
+ ::Microsoft::Windows::PushNotifications::PushNotificationChannelStatus result = wrapper->_instance->Status;
+ info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ private:
+ ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ _instance;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+
+ friend v8::Local<v8::Value> WrapPushNotificationCreateChannelResult(::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ wintRtInstance);
+ friend ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ UnwrapPushNotificationCreateChannelResult(Local<Value> value);
+ };
+
+ Persistent<FunctionTemplate> PushNotificationCreateChannelResult::s_constructorTemplate;
+
+ v8::Local<v8::Value> WrapPushNotificationCreateChannelResult(::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ winRtInstance)
+ {
+ EscapableHandleScope scope;
+
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
+ Local<Value> args[] = {opaqueWrapper};
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(PushNotificationCreateChannelResult::s_constructorTemplate);
+ return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), _countof(args), args).ToLocalChecked());
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^ UnwrapPushNotificationCreateChannelResult(Local<Value> value) {
+ return PushNotificationCreateChannelResult::Unwrap<PushNotificationCreateChannelResult>(Nan::To<Object>(value).ToLocalChecked())->_instance;
+ }
+
+ void InitPushNotificationCreateChannelResult(Local<Object> exports)
+ {
+ PushNotificationCreateChannelResult::Init(exports);
+ }
+
+ class PushNotificationManager : public WrapperBase
+ {
+ public:
+ static void Init(const Local<Object> exports)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(Nan::New<String>("PushNotificationManager").ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Local<Function> func;
+ Local<FunctionTemplate> funcTemplate;
+
+ Nan::SetPrototypeMethod(localRef, "register", Register);
+ Nan::SetPrototypeMethod(localRef, "unregister", Unregister);
+ Nan::SetPrototypeMethod(localRef, "unregisterAll", UnregisterAll);
+
+ Nan::SetPrototypeMethod(localRef, "createChannelAsync", CreateChannelAsync);
+
+ Nan::SetPrototypeMethod(localRef, "addListener", AddListener);
+ Nan::SetPrototypeMethod(localRef, "on", AddListener);
+ Nan::SetPrototypeMethod(localRef, "removeListener", RemoveListener);
+ Nan::SetPrototypeMethod(localRef, "off", RemoveListener);
+
+ Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
+ Nan::SetMethod(constructor, "castFrom", CastFrom);
+
+ Nan::SetMethod(constructor, "isSupported", IsSupported);
+ Nan::SetAccessor(constructor, Nan::New<String>("default").ToLocalChecked(), DefaultGetter);
+
+ Nan::Set(exports, Nan::New<String>("PushNotificationManager").ToLocalChecked(), constructor);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ PushNotificationManager(::Microsoft::Windows::PushNotifications::PushNotificationManager ^ instance)
+ {
+ _instance = instance;
+ }
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);
+
+ // in case the constructor was called without the new operator
+ if (!localRef->HasInstance(info.This()))
+ {
+ if (info.Length() > 0)
+ {
+ std::unique_ptr<Local<Value>[]> constructorArgs(new Local<Value>[info.Length()]);
+
+ Local<Value> *argsPtr = constructorArgs.get();
+ for (int i = 0; i < info.Length(); i++)
+ {
+ argsPtr[i] = info[i];
+ }
+
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ else
+ {
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);
+
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationManager ^ winRtInstance;
+
+ if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
+ NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info[0]))
+ {
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationManager ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
+ return;
+ }
+
+ NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());
+
+ PushNotificationManager *wrapperInstance = new PushNotificationManager(winRtInstance);
+ wrapperInstance->Wrap(info.This());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+ if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info[0]))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
+ return;
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationManager ^ winRtInstance;
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationManager ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+
+ info.GetReturnValue().Set(WrapPushNotificationManager(winRtInstance));
+ }
+
+ static void CreateChannelAsync(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info.This()))
+ {
+ return;
+ }
+
+ if (info.Length() == 0 || !info[info.Length() - 1]->IsFunction())
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
+ return;
+ }
+
+ PushNotificationManager *wrapper = PushNotificationManager::Unwrap<PushNotificationManager>(info.This());
+
+ ::Windows::Foundation::IAsyncOperationWithProgress<::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^, ::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelStatus> ^ op;
+
+ if (info.Length() == 2 && NodeRT::Utils::IsGuid(info[0]))
+ {
+ try
+ {
+ ::Platform::Guid arg0 = NodeRT::Utils::GuidFromJs(info[0]);
+
+ op = wrapper->_instance->CreateChannelAsync(arg0);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
+ return;
+ }
+
+ auto opTask = create_task(op);
+ uv_async_t *asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() - 1].As<Function>());
+
+ opTask.then([asyncToken](task<::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult ^> t)
+ {
+ try {
+ auto result = t.get();
+ NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {
+
+
+ Local<Value> error;
+ Local<Value> arg1;
+ {
+ TryCatch tryCatch;
+ arg1 = WrapPushNotificationCreateChannelResult(result);
+ if (tryCatch.HasCaught())
+ {
+ error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
+ }
+ else
+ {
+ error = Undefined();
+ }
+ if (arg1.IsEmpty()) arg1 = Undefined();
+ }
+ Local<Value> args[] = {error, arg1};
+
+
+ invokeCallback(_countof(args), args);
+ });
+ } catch (Platform::Exception^ exception) {
+ NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
+ Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
+
+ Local<Value> args[] = {error};
+ invokeCallback(_countof(args), args);
+ });
+ } });
+ }
+
+ static void Register(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationManager *wrapper = PushNotificationManager::Unwrap<PushNotificationManager>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ wrapper->_instance->Register();
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+ static void Unregister(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationManager *wrapper = PushNotificationManager::Unwrap<PushNotificationManager>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ wrapper->_instance->Unregister();
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+ static void UnregisterAll(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationManager *wrapper = PushNotificationManager::Unwrap<PushNotificationManager>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ wrapper->_instance->UnregisterAll();
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void IsSupported(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ bool result;
+ result = ::Microsoft::Windows::PushNotifications::PushNotificationManager::IsSupported();
+ info.GetReturnValue().Set(Nan::New<Boolean>(result));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void DefaultGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ try
+ {
+ ::Microsoft::Windows::PushNotifications::PushNotificationManager ^ result = ::Microsoft::Windows::PushNotifications::PushNotificationManager::Default;
+ info.GetReturnValue().Set(WrapPushNotificationManager(result));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction())
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
+ return;
+ }
+
+ String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
+ auto str = *eventName;
+
+ Local<Function> callback = info[1].As<Function>();
+
+ ::Windows::Foundation::EventRegistrationToken registrationToken;
+ if (NodeRT::Utils::CaseInsenstiveEquals(L"pushReceived", str))
+ {
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info.This()))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
+ return;
+ }
+ PushNotificationManager *wrapper = PushNotificationManager::Unwrap<PushNotificationManager>(info.This());
+
+ try
+ {
+ Persistent<Object> *perstPtr = new Persistent<Object>();
+ perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
+ std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
+ [](Persistent<Object> *ptr)
+ {
+ NodeUtils::Async::RunOnMain([ptr]()
+ {
+ ptr->Reset();
+ delete ptr; });
+ });
+
+ registrationToken = wrapper->_instance->PushReceived::add(
+ ref new ::Windows::Foundation::TypedEventHandler<::Microsoft::Windows::PushNotifications::PushNotificationManager ^, ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^>(
+ [callbackObjPtr](::Microsoft::Windows::PushNotifications::PushNotificationManager ^ arg0, ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ arg1)
+ {
+ NodeUtils::Async::RunOnMain([callbackObjPtr, arg0, arg1]()
+ {
+ HandleScope scope;
+
+
+ Local<Value> wrappedArg0;
+ Local<Value> wrappedArg1;
+
+ {
+ TryCatch tryCatch;
+
+
+ wrappedArg0 = WrapPushNotificationManager(arg0);
+ wrappedArg1 = WrapPushNotificationReceivedEventArgs(arg1);
+
+
+ if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
+ if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
+ }
+
+ Local<Value> args[] = { wrappedArg0, wrappedArg1 };
+ Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
+ NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args); });
+ }));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
+ return;
+ }
+
+ Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
+ Local<Object> tokenMap;
+
+ if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false))
+ {
+ tokenMap = Nan::New<Object>();
+ NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
+ }
+ else
+ {
+ tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
+ }
+
+ Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
+ }
+
+ static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction())
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
+ return;
+ }
+
+ String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
+ auto str = *eventName;
+
+ if ((!NodeRT::Utils::CaseInsenstiveEquals(L"pushReceived", str)))
+ {
+ Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
+ return;
+ }
+
+ Local<Function> callback = info[1].As<Function>();
+ Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
+
+ if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false))
+ {
+ return;
+ }
+
+ Local<Value> opaqueWrapperObj = Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();
+
+ if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj, Undefined()).FromMaybe(false))
+ {
+ return;
+ }
+
+ OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());
+
+ long long tokenValue = (long long)opaqueWrapper->GetObjectInstance();
+ ::Windows::Foundation::EventRegistrationToken registrationToken;
+ registrationToken.Value = tokenValue;
+
+ try
+ {
+ if (NodeRT::Utils::CaseInsenstiveEquals(L"pushReceived", str))
+ {
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationManager ^>(info.This()))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
+ return;
+ }
+ PushNotificationManager *wrapper = PushNotificationManager::Unwrap<PushNotificationManager>(info.This());
+ wrapper->_instance->PushReceived::remove(registrationToken);
+ }
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ }
+
+ Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
+ }
+
+ private:
+ ::Microsoft::Windows::PushNotifications::PushNotificationManager ^ _instance;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+
+ friend v8::Local<v8::Value> WrapPushNotificationManager(::Microsoft::Windows::PushNotifications::PushNotificationManager ^ wintRtInstance);
+ friend ::Microsoft::Windows::PushNotifications::PushNotificationManager ^ UnwrapPushNotificationManager(Local<Value> value);
+ };
+
+ Persistent<FunctionTemplate> PushNotificationManager::s_constructorTemplate;
+
+ v8::Local<v8::Value> WrapPushNotificationManager(::Microsoft::Windows::PushNotifications::PushNotificationManager ^ winRtInstance)
+ {
+ EscapableHandleScope scope;
+
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
+ Local<Value> args[] = {opaqueWrapper};
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(PushNotificationManager::s_constructorTemplate);
+ return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), _countof(args), args).ToLocalChecked());
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationManager ^ UnwrapPushNotificationManager(Local<Value> value) {
+ return PushNotificationManager::Unwrap<PushNotificationManager>(Nan::To<Object>(value).ToLocalChecked())->_instance;
+ }
+
+ void InitPushNotificationManager(Local<Object> exports)
+ {
+ PushNotificationManager::Init(exports);
+ }
+
+ class PushNotificationReceivedEventArgs : public WrapperBase
+ {
+ public:
+ static void Init(const Local<Object> exports)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
+ s_constructorTemplate.Reset(localRef);
+ localRef->SetClassName(Nan::New<String>("PushNotificationReceivedEventArgs").ToLocalChecked());
+ localRef->InstanceTemplate()->SetInternalFieldCount(1);
+
+ Nan::SetPrototypeMethod(localRef, "getDeferral", GetDeferral);
+
+ Nan::SetPrototypeMethod(localRef, "addListener", AddListener);
+ Nan::SetPrototypeMethod(localRef, "on", AddListener);
+ Nan::SetPrototypeMethod(localRef, "removeListener", RemoveListener);
+ Nan::SetPrototypeMethod(localRef, "off", RemoveListener);
+
+ Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("payload").ToLocalChecked(), PayloadGetter);
+
+ Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
+ Nan::SetMethod(constructor, "castFrom", CastFrom);
+
+ Nan::Set(exports, Nan::New<String>("PushNotificationReceivedEventArgs").ToLocalChecked(), constructor);
+ }
+
+ virtual ::Platform::Object ^ GetObjectInstance() const override
+ {
+ return _instance;
+ }
+
+ private:
+ PushNotificationReceivedEventArgs(::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ instance)
+ {
+ _instance = instance;
+ }
+
+ static void New(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);
+
+ // in case the constructor was called without the new operator
+ if (!localRef->HasInstance(info.This()))
+ {
+ if (info.Length() > 0)
+ {
+ std::unique_ptr<Local<Value>[]> constructorArgs(new Local<Value>[info.Length()]);
+
+ Local<Value> *argsPtr = constructorArgs.get();
+ for (int i = 0; i < info.Length(); i++)
+ {
+ argsPtr[i] = info[i];
+ }
+
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ else
+ {
+ MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);
+
+ if (res.IsEmpty())
+ {
+ return;
+ }
+
+ info.GetReturnValue().Set(res.ToLocalChecked());
+ return;
+ }
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ winRtInstance;
+
+ if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
+ NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^>(info[0]))
+ {
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
+ return;
+ }
+
+ NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());
+
+ PushNotificationReceivedEventArgs *wrapperInstance = new PushNotificationReceivedEventArgs(winRtInstance);
+ wrapperInstance->Wrap(info.This());
+
+ info.GetReturnValue().Set(info.This());
+ }
+
+ static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+ if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^>(info[0]))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
+ return;
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ winRtInstance;
+ try
+ {
+ winRtInstance = (::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^) NodeRT::Utils::GetObjectInstance(info[0]);
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+
+ info.GetReturnValue().Set(WrapPushNotificationReceivedEventArgs(winRtInstance));
+ }
+
+ static void GetDeferral(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationReceivedEventArgs *wrapper = PushNotificationReceivedEventArgs::Unwrap<PushNotificationReceivedEventArgs>(info.This());
+
+ if (info.Length() == 0)
+ {
+ try
+ {
+ ::Windows::ApplicationModel::Background::BackgroundTaskDeferral ^ result;
+ result = wrapper->_instance->GetDeferral();
+ info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.ApplicationModel.Background", "BackgroundTaskDeferral", result));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
+ return;
+ }
+ }
+
+ static void PayloadGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
+ {
+ HandleScope scope;
+
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^>(info.This()))
+ {
+ return;
+ }
+
+ PushNotificationReceivedEventArgs *wrapper = PushNotificationReceivedEventArgs::Unwrap<PushNotificationReceivedEventArgs>(info.This());
+
+ try
+ {
+ ::Platform::Array<unsigned char> ^ result = wrapper->_instance->Payload;
+ info.GetReturnValue().Set(NodeRT::Collections::ArrayWrapper<unsigned char>::CreateArrayWrapper(
+ result,
+ [](unsigned char val) -> Local<Value>
+ {
+ return Nan::New<Integer>(val);
+ },
+ [](Local<Value> value) -> bool
+ {
+ return value->IsInt32();
+ },
+ [](Local<Value> value) -> unsigned char
+ {
+ return static_cast<unsigned char>(Nan::To<int32_t>(value).FromMaybe(0));
+ }));
+ return;
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+
+ static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction())
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
+ return;
+ }
+
+ String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
+ auto str = *eventName;
+
+ Local<Function> callback = info[1].As<Function>();
+
+ ::Windows::Foundation::EventRegistrationToken registrationToken;
+ if (NodeRT::Utils::CaseInsenstiveEquals(L"canceled", str))
+ {
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^>(info.This()))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
+ return;
+ }
+ PushNotificationReceivedEventArgs *wrapper = PushNotificationReceivedEventArgs::Unwrap<PushNotificationReceivedEventArgs>(info.This());
+
+ try
+ {
+ Persistent<Object> *perstPtr = new Persistent<Object>();
+ perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
+ std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
+ [](Persistent<Object> *ptr)
+ {
+ NodeUtils::Async::RunOnMain([ptr]()
+ {
+ ptr->Reset();
+ delete ptr; });
+ });
+
+ registrationToken = wrapper->_instance->Canceled::add(
+ ref new ::Windows::ApplicationModel::Background::BackgroundTaskCanceledEventHandler(
+ [callbackObjPtr](::Windows::ApplicationModel::Background::IBackgroundTaskInstance ^ arg0, ::Windows::ApplicationModel::Background::BackgroundTaskCancellationReason arg1)
+ {
+ NodeUtils::Async::RunOnMain([callbackObjPtr, arg0, arg1]()
+ {
+ HandleScope scope;
+
+
+ Local<Value> wrappedArg0;
+ Local<Value> wrappedArg1;
+
+ {
+ TryCatch tryCatch;
+
+
+ wrappedArg0 = NodeRT::Utils::CreateExternalWinRTObject("Windows.ApplicationModel.Background", "IBackgroundTaskInstance", arg0);
+ wrappedArg1 = Nan::New<Integer>(static_cast<int>(arg1));
+
+
+ if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
+ if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
+ }
+
+ Local<Value> args[] = { wrappedArg0, wrappedArg1 };
+ Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
+ NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args); });
+ }));
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ return;
+ }
+ }
+ else
+ {
+ Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
+ return;
+ }
+
+ Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
+ Local<Object> tokenMap;
+
+ if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false))
+ {
+ tokenMap = Nan::New<Object>();
+ NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
+ }
+ else
+ {
+ tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
+ }
+
+ Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
+ }
+
+ static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info)
+ {
+ HandleScope scope;
+
+ if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction())
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
+ return;
+ }
+
+ String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
+ auto str = *eventName;
+
+ if ((!NodeRT::Utils::CaseInsenstiveEquals(L"canceled", str)))
+ {
+ Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
+ return;
+ }
+
+ Local<Function> callback = info[1].As<Function>();
+ Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
+
+ if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false))
+ {
+ return;
+ }
+
+ Local<Value> opaqueWrapperObj = Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();
+
+ if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj, Undefined()).FromMaybe(false))
+ {
+ return;
+ }
+
+ OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());
+
+ long long tokenValue = (long long)opaqueWrapper->GetObjectInstance();
+ ::Windows::Foundation::EventRegistrationToken registrationToken;
+ registrationToken.Value = tokenValue;
+
+ try
+ {
+ if (NodeRT::Utils::CaseInsenstiveEquals(L"canceled", str))
+ {
+ if (!NodeRT::Utils::IsWinRtWrapperOf<::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^>(info.This()))
+ {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
+ return;
+ }
+ PushNotificationReceivedEventArgs *wrapper = PushNotificationReceivedEventArgs::Unwrap<PushNotificationReceivedEventArgs>(info.This());
+ wrapper->_instance->Canceled::remove(registrationToken);
+ }
+ }
+ catch (Platform::Exception ^ exception)
+ {
+ NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
+ }
+
+ Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
+ }
+
+ private:
+ ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ _instance;
+ static Persistent<FunctionTemplate> s_constructorTemplate;
+
+ friend v8::Local<v8::Value> WrapPushNotificationReceivedEventArgs(::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ wintRtInstance);
+ friend ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ UnwrapPushNotificationReceivedEventArgs(Local<Value> value);
+ };
+
+ Persistent<FunctionTemplate> PushNotificationReceivedEventArgs::s_constructorTemplate;
+
+ v8::Local<v8::Value> WrapPushNotificationReceivedEventArgs(::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ winRtInstance)
+ {
+ EscapableHandleScope scope;
+
+ if (winRtInstance == nullptr)
+ {
+ return scope.Escape(Undefined());
+ }
+
+ Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
+ Local<Value> args[] = {opaqueWrapper};
+ Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(PushNotificationReceivedEventArgs::s_constructorTemplate);
+ return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), _countof(args), args).ToLocalChecked());
+ }
+
+ ::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs ^ UnwrapPushNotificationReceivedEventArgs(Local<Value> value) {
+ return PushNotificationReceivedEventArgs::Unwrap<PushNotificationReceivedEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
+ }
+
+ void InitPushNotificationReceivedEventArgs(Local<Object> exports)
+ {
+ PushNotificationReceivedEventArgs::Init(exports);
+ }
+
+ }
+ }
+ }
+}
+
+NAN_MODULE_INIT(init)
+{
+ // We ignore failures for now since it probably means that
+ // the initialization already happened for STA, and that's cool
+
+ CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+
+ /*
+ if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
+ Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"error in CoInitializeEx()")));
+ return;
+ }
+ */
+
+ NodeRT::Microsoft::Windows::PushNotifications::InitPushNotificationChannelStatusEnum(target);
+ NodeRT::Microsoft::Windows::PushNotifications::InitPushNotificationChannel(target);
+ NodeRT::Microsoft::Windows::PushNotifications::InitPushNotificationCreateChannelResult(target);
+ NodeRT::Microsoft::Windows::PushNotifications::InitPushNotificationManager(target);
+ NodeRT::Microsoft::Windows::PushNotifications::InitPushNotificationReceivedEventArgs(target);
+
+ NodeRT::Utils::RegisterNameSpace("Microsoft.Windows.PushNotifications", target);
+}
+
+NODE_MODULE(binding, init)
\ No newline at end of file
diff --git a/desktop/addons/windows-pushnotifications/binding.gyp b/desktop/addons/windows-pushnotifications/binding.gyp
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/binding.gyp
@@ -0,0 +1,43 @@
+{
+ "variables": {
+ "USE_ADDITIONAL_WINMD": "true"
+ },
+ "includes": ["common.gypi"],
+ "targets": [{
+ "target_name": "binding",
+ "sources": [],
+ "include_dirs": [
+ "<!(node -e \"require('nan')\")"
+ ],
+ "libraries": [],
+ "conditions": [
+ ["OS=='win'", {
+ "libraries": ["-lruntimeobject.lib"],
+ "sources": [
+ "_nodert_generated.cpp",
+ "NodeRtUtils.cpp",
+ "OpaqueWrapper.cpp",
+ "CollectionsConverterUtils.cpp"
+ ]
+ }],
+ ["USE_ADDITIONAL_WINMD==\"true\"", {
+ "msvs_settings": {
+ "VCCLCompilerTool": {
+ "AdditionalUsingDirectories": [
+ "%ProgramFiles%/Windows Kits/10/UnionMetadata/windows-pushnotifications",
+ "%ProgramFiles%/Windows Kits/10/Include/windows-pushnotifications/um",
+ "%ProgramFiles(x86)%/Windows Kits/10/UnionMetadata/windows-pushnotifications",
+ "%ProgramFiles(x86)%/Windows Kits/10/Include/windows-pushnotifications/um"
+ ]
+ }
+ }
+ }]
+ ],
+ "msvs_settings": {
+ "VCCLCompilerTool": {
+ "AdditionalOptions": ["/ZW"],
+ "DisableSpecificWarnings": [4609]
+ }
+ }
+ }]
+}
\ No newline at end of file
diff --git a/desktop/addons/windows-pushnotifications/common.gypi b/desktop/addons/windows-pushnotifications/common.gypi
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/common.gypi
@@ -0,0 +1,26 @@
+{
+ 'variables': {
+ 'node_shared': 'true'
+ },
+ 'target_defaults': {
+ 'default_configuration': 'Release',
+ 'configurations': {
+ 'Debug': {
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ExceptionHandling': 1, # /EHsc,
+ 'RuntimeLibrary': '3', # /MDd
+ }
+ }
+ },
+ 'Release': {
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ExceptionHandling': 1, # /EHsc,
+ 'RuntimeLibrary': '2', # /MD
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/desktop/addons/windows-pushnotifications/lib/main.js b/desktop/addons/windows-pushnotifications/lib/main.js
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/lib/main.js
@@ -0,0 +1,70 @@
+/* eslint-disable */
+
+// Copyright (c) Microsoft Corporation, Nadav Bar, and Felix Rieseberg
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing permissions
+// and limitations under the License.
+
+const path = require('path');
+const fs = require('fs');
+
+const npmScope = '';
+
+// This little trick makes Node.js Tools for VS load IntelliSense for the module
+if (fs.existsSync(path.join(__dirname, 'NodeRT_Microsoft_Windows_PushNotifications.d.js)'))) {
+ module.exports = require('./NodeRT_Microsoft_Windows_PushNotifications.d.js');
+} else {
+ module.exports = require('../build/Release/binding.node');
+}
+
+var externalReferencedNamespaces = ['Windows.Foundation', 'Windows.ApplicationModel.Background'];
+
+if (externalReferencedNamespaces.length > 0) {
+ var namespaceRegistry = global.__winRtNamespaces__;
+
+ if (!namespaceRegistry) {
+ namespaceRegistry = {};
+
+ Object.defineProperty(global, '__winRtNamespaces__', {
+ configurable: true,
+ writable: false,
+ enumerable: false,
+ value: namespaceRegistry
+ });
+ }
+
+ function requireNamespace(namespace) {
+ var moduleName = namespace.toLowerCase();
+
+ if (npmScope) {
+ moduleName = '@' + npmScope + '/' + moduleName;
+ }
+
+ var m = require(moduleName);
+ delete namespaceRegistry[namespace];
+ namespaceRegistry[namespace] = m;
+ return m;
+ }
+
+ for (var i in externalReferencedNamespaces) {
+ var ns = externalReferencedNamespaces[i];
+
+ if (!namespaceRegistry.hasOwnProperty(ns)) {
+ Object.defineProperty(namespaceRegistry, ns, {
+ configurable: true,
+ enumerable: true,
+ get: requireNamespace.bind(null, ns)
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/desktop/addons/windows-pushnotifications/node-async.h b/desktop/addons/windows-pushnotifications/node-async.h
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/node-async.h
@@ -0,0 +1,422 @@
+// Copyright (c) The NodeRT Contributors
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the ""License""); you may
+// not use this file except in compliance with the License. You may obtain a
+// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABLITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+#pragma once
+
+#include <v8.h>
+#include "nan.h"
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#if NAUV_UVVERSION < 0x000b17
+#define NODEASYNC_ASYNC_WORK_CB(func) \
+ static void __cdecl func(uv_async_t *handle, int)
+#define NODEASYNC_IDLE_WORK_CB(func) \
+ static void __cdecl func(uv_idle_t *handle, int)
+#else
+#define NODEASYNC_ASYNC_WORK_CB(func) \
+ static void __cdecl func(uv_async_t *handle)
+#define NODEASYNC_IDLE_WORK_CB(func) static void __cdecl func(uv_idle_t *handle)
+#endif
+
+namespace NodeUtils
+{
+ using Nan::EscapableHandleScope;
+ using Nan::GetCurrentContext;
+ using Nan::HandleScope;
+ using Nan::New;
+ using Nan::Null;
+ using Nan::Persistent;
+ using Nan::Undefined;
+ using v8::Exception;
+ using v8::Function;
+ using v8::Integer;
+ using v8::Local;
+ using v8::Object;
+ using v8::String;
+ using v8::Value;
+
+ typedef std::function<void(int, Local<Value> *)> InvokeCallbackDelegate;
+
+ class Async
+ {
+ public:
+ template <typename TInput, typename TResult>
+ struct Baton
+ {
+ int error_code;
+ std::wstring error_message;
+
+ // Custom data
+ std::shared_ptr<TInput> data;
+ std::shared_ptr<TResult> result;
+ std::shared_ptr<Persistent<Value>> callback_args;
+ unsigned callback_args_size;
+
+ Baton() { callback_args_size = 0; }
+
+ void setCallbackArgs(Local<Value> *argv, int argc)
+ {
+ HandleScope scope;
+
+ callback_info.reset(new Persistent<Value>[argc],
+ [](Persistent<Value> *ptr)
+ { delete[] ptr; });
+
+ callback_args_size = 0;
+
+ for (int i = 0; i < argc; i++)
+ {
+ // callback_info.get()[i] = argv[i];
+ callback_info.get()[i].Reset(argv[i]);
+ }
+ }
+
+ virtual ~Baton()
+ {
+ for (int i = 0; i < callback_args_size; i++)
+ {
+ callback_info.get()[i].Reset();
+ }
+ }
+
+ private:
+ uv_work_t request;
+ std::function<void(Baton *)> doWork;
+ std::function<void(Baton *)> afterWork;
+ Nan::Persistent<Object> callbackData;
+
+ friend Async;
+ };
+
+ private:
+ class TokenData
+ {
+ public:
+ static uv_async_t *NewAsyncToken()
+ {
+ uv_async_t *asyncHandle = new uv_async_t;
+ uv_async_init(uv_default_loop(), asyncHandle, AsyncCb);
+ SetHandleData(asyncHandle->data);
+
+ return asyncHandle;
+ }
+
+ static uv_async_t *NewAsyncToken(Local<Function> callback,
+ Local<Value> receiver)
+ {
+ uv_async_t *asyncHandle = NewAsyncToken();
+ SetHandleCallbackData(asyncHandle->data, callback, receiver);
+
+ return asyncHandle;
+ }
+
+ static uv_idle_t *NewIdleToken()
+ {
+ uv_idle_t *idleHandle = new uv_idle_t;
+ uv_idle_init(uv_default_loop(), idleHandle);
+
+ SetHandleData(idleHandle->data);
+ return idleHandle;
+ }
+
+ static uv_idle_t *NewIdleToken(Local<Function> callback,
+ Local<Value> receiver)
+ {
+ uv_idle_t *idleHandle = NewIdleToken();
+ SetHandleCallbackData(idleHandle->data, callback, receiver);
+
+ return idleHandle;
+ }
+
+ virtual ~TokenData() { callbackData.Reset(); }
+
+ private:
+ static void SetHandleData(void *&handleData)
+ {
+ handleData = new TokenData();
+ }
+
+ static void SetHandleCallbackData(void *handleData,
+ Local<Function> callback,
+ Local<Value> receiver)
+ {
+ TokenData *Token = static_cast<TokenData *>(handleData);
+ Token->callbackData.Reset(CreateCallbackData(callback, receiver));
+ }
+
+ TokenData() {}
+
+ Persistent<Object> callbackData;
+ std::function<void()> func;
+
+ friend Async;
+ };
+
+ public:
+ template <typename TInput, typename TResult>
+ static void __cdecl Run(
+ std::shared_ptr<TInput> input,
+ std::function<void(Baton<TInput, TResult> *)> doWork,
+ std::function<void(Baton<TInput, TResult> *)> afterWork,
+ Local<Function> callback,
+ Local<Value> receiver = Local<Value>())
+ {
+ HandleScope scope;
+ Local<Object> callbackData = CreateCallbackData(callback, receiver);
+
+ Baton<TInput, TResult> *baton = new Baton<TInput, TResult>();
+ baton->request.data = baton;
+ baton->callbackData.Reset(callbackData);
+ baton->error_code = 0;
+ baton->data = input;
+ baton->doWork = doWork;
+ baton->afterWork = afterWork;
+
+ uv_queue_work(uv_default_loop(), &baton->request,
+ AsyncWork<TInput, TResult>, AsyncAfter<TInput, TResult>);
+ }
+
+ static uv_async_t *__cdecl GetAsyncToken()
+ {
+ return TokenData::NewAsyncToken();
+ }
+
+ static uv_async_t *__cdecl GetAsyncToken(
+ Local<Function> callback,
+ Local<Value> receiver = Local<Value>())
+ {
+ return TokenData::NewAsyncToken(callback, receiver);
+ }
+
+ static uv_idle_t *__cdecl GetIdleToken() { return TokenData::NewIdleToken(); }
+
+ static uv_idle_t *__cdecl GetIdleToken(
+ Local<Function> callback,
+ Local<Value> receiver = Local<Value>())
+ {
+ return TokenData::NewIdleToken(callback, receiver);
+ }
+
+ static void __cdecl RunOnMain(uv_async_t *async, std::function<void()> func)
+ {
+ TokenData *Token = static_cast<TokenData *>(async->data);
+ Token->func = func;
+ uv_async_send(async);
+ }
+
+ static void __cdecl RunOnMain(std::function<void()> func)
+ {
+ uv_async_t *async = GetAsyncToken();
+ RunOnMain(async, func);
+ }
+
+ static void __cdecl RunCallbackOnMain(
+ uv_async_t *async,
+ std::function<void(InvokeCallbackDelegate invokeCallback)> func)
+ {
+ TokenData *Token = static_cast<TokenData *>(async->data);
+
+ InvokeCallbackDelegate invokeCallback = [Token](int argc,
+ Local<Value> *argv)
+ {
+ if (!Token->callbackData.IsEmpty())
+ {
+ Nan::AsyncResource asyncResource(Nan::New<String>("RunCallbackOnMain").ToLocalChecked());
+ asyncResource.runInAsyncScope(New(Token->callbackData),
+ New<String>("callback").ToLocalChecked(), argc, argv);
+ }
+ };
+
+ std::function<void()> wrapper = [func, invokeCallback]()
+ {
+ HandleScope scope;
+ func(invokeCallback);
+ };
+
+ RunOnMain(async, wrapper);
+ }
+
+ // defers execution of the provided function by creating an idler
+ // that means, the function will be invoked once the event loop has delivered
+ // all pending events.
+ static void __cdecl NextTick(std::function<void()> func)
+ {
+ uv_idle_t *idler = GetIdleToken();
+ NextTick(idler, func);
+ }
+
+ static void __cdecl NextTick(uv_idle_t *idler, std::function<void()> func)
+ {
+ TokenData *Token = static_cast<TokenData *>(idler->data);
+ Token->func = func;
+
+ uv_idle_start(idler, onNextTick);
+ }
+
+ static void __cdecl RunCallbackOnNextTick(
+ uv_idle_t *idler,
+ std::function<void(InvokeCallbackDelegate invokeCallback)> func)
+ {
+ TokenData *Token = static_cast<TokenData *>(idler->data);
+
+ InvokeCallbackDelegate invokeCallback = [Token](int argc,
+ Local<Value> *argv)
+ {
+ if (!Token->callbackData.IsEmpty())
+ {
+ Nan::AsyncResource asyncResource(Nan::New<String>("RunCallbackOnNextTick").ToLocalChecked());
+ asyncResource.runInAsyncScope(New(Token->callbackData),
+ New<String>("callback").ToLocalChecked(), argc, argv);
+ }
+ };
+
+ std::function<void()> wrapper = [func, invokeCallback]()
+ {
+ HandleScope scope;
+ func(invokeCallback);
+ };
+
+ NextTick(idler, wrapper);
+ }
+
+ private:
+ static Local<Object> CreateCallbackData(Local<Function> callback,
+ Local<Value> receiver)
+ {
+ EscapableHandleScope scope;
+
+ Local<Object> callbackData;
+ if (!callback.IsEmpty() && !callback->Equals(Nan::GetCurrentContext(), Undefined()).FromMaybe(true))
+ {
+ callbackData = New<Object>();
+
+ if (!receiver.IsEmpty())
+ {
+ Nan::SetPrototype(callbackData, receiver);
+ }
+
+ Nan::Set(callbackData, New<String>("callback").ToLocalChecked(),
+ callback);
+
+ // get the current domain:
+ Local<Value> currentDomain = Undefined();
+
+ Local<Object> process =
+ Nan::To<Object>(Nan::Get(GetCurrentContext()->Global(),
+ New<String>("process").ToLocalChecked())
+ .ToLocalChecked())
+ .ToLocalChecked();
+ if (!process->Equals(Nan::GetCurrentContext(), Undefined()).FromMaybe(true))
+ {
+ currentDomain = process->Get(Nan::GetCurrentContext(), New<String>("domain").ToLocalChecked()).ToLocalChecked();
+ }
+
+ Nan::Set(callbackData, New<String>("domain").ToLocalChecked(),
+ currentDomain);
+ }
+
+ return scope.Escape(callbackData);
+ };
+
+ template <typename TInput, typename TResult>
+ static void __cdecl AsyncWork(uv_work_t *req)
+ {
+ // No HandleScope!
+
+ Baton<TInput, TResult> *baton =
+ static_cast<Baton<TInput, TResult> *>(req->data);
+
+ // Do work in threadpool here.
+ // Set baton->error_code/message on failures.
+ // Set baton->result with a final result object
+ baton->doWork(baton);
+ }
+
+ template <typename TInput, typename TResult>
+ static void __cdecl AsyncAfter(uv_work_t *req, int status)
+ {
+ HandleScope scope;
+ ;
+ Baton<TInput, TResult> *baton =
+ static_cast<Baton<TInput, TResult> *>(req->data);
+
+ // typical AfterWorkFunc implementation
+ // if (baton->error)
+ //{
+ // Local<Value> err = Exception::Error(...);
+ // Local<Value> argv[] = { err };
+ // baton->setCallbackArgs(argv, _countof(argv));
+ //}
+ // else
+ //{
+ // Local<Value> argv[] = { Undefined(), ... };
+ // baton->setCallbackArgs(argv, _countof(argv));
+ //}
+
+ baton->afterWork(baton);
+
+ if (!baton->callbackData.IsEmpty())
+ {
+ // call the callback, using domains and all
+ int argc = static_cast<int>(baton->callback_args_size);
+ std::unique_ptr<Local<Value>> handlesArr(new Local<Value>[argc]);
+ for (int i = 0; i < argc; i++)
+ {
+ handlesArr.get()[i] = New(baton->callback_info.get()[i]);
+ }
+
+ Nan::AsyncResource asyncResource(Nan::New<String>("AsyncAfter").ToLocalChecked());
+ asyncResource.callInAsyncScope(New(baton->callbackData),
+ New<String>("callback").ToLocalChecked(), argc,
+ handlesArr.get());
+ }
+
+ baton->callbackData.Reset();
+ delete baton;
+ }
+
+ // called after the async handle is closed in order to free it's memory
+ static void __cdecl AyncCloseCb(uv_handle_t *handle)
+ {
+ if (handle != nullptr)
+ {
+ uv_async_t *async = reinterpret_cast<uv_async_t *>(handle);
+ delete async;
+ }
+ }
+
+ // Called by run on main in case we are not running on the main thread
+ NODEASYNC_ASYNC_WORK_CB(AsyncCb)
+ {
+ auto Token = static_cast<TokenData *>(handle->data);
+ Token->func();
+ uv_close((uv_handle_t *)handle, AyncCloseCb);
+ delete Token;
+ }
+
+ NODEASYNC_IDLE_WORK_CB(onNextTick)
+ {
+ std::function<void()> *func =
+ static_cast<std::function<void()> *>(handle->data);
+ (*func)();
+ delete func;
+ uv_idle_stop(handle);
+ delete handle;
+ }
+ };
+} // namespace NodeUtils
diff --git a/desktop/addons/windows-pushnotifications/package.json b/desktop/addons/windows-pushnotifications/package.json
new file mode 100644
--- /dev/null
+++ b/desktop/addons/windows-pushnotifications/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "microsoft.windows.pushnotifications",
+ "version": "0.0.1",
+ "description": "Use the Microsoft.Windows.PushNotifications UWP API directly from Node.js",
+ "main": "lib/main.js",
+ "keywords": [
+ "Microsoft.Windows.PushNotifications",
+ "Microsoft",
+ "Windows",
+ "PushNotifications",
+ "PushNotificationChannel",
+ "PushNotificationCreateChannelResult",
+ "PushNotificationManager",
+ "PushNotificationReceivedEventArgs",
+ "PushNotificationChannelStatus",
+ "PushNotificationCreateChannelStatus",
+ "PushNotificationsContract",
+ "NodeRT",
+ "WinRT",
+ "Microsoft"
+ ],
+ "dependencies": {
+ "nan": "2.17.0"
+ },
+ "devDependencies": {
+ "node-gyp": "^9.3.1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/NodeRT/NodeRT.git"
+ },
+ "homepage": "https://github.com/NodeRT/NodeRT",
+ "author": "Generated by NodeRT",
+ "contributors": [
+ "nadavbar <nadavbar@gmail.com> (http://www.nadavos.com)",
+ "Felix Rieseberg <felix@felixrieseberg.com> (https://www.felix.fun)"
+ ],
+ "gypfile": true,
+ "license": "Apache-2.0"
+}
diff --git a/desktop/forge.config.cjs b/desktop/forge.config.cjs
--- a/desktop/forge.config.cjs
+++ b/desktop/forge.config.cjs
@@ -124,6 +124,7 @@
'\\.eslintrc\\.json',
'\\.flowconfig',
'flow-typed',
+ 'addons',
],
appBundleId: 'app.comm.macos',
...signingOptions.packagerMacos,

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 14, 8:51 AM (3 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5931171
Default Alt Text
D7250.1768380683.diff (231 KB)

Event Timeline