[
  {
    "path": ".gitignore",
    "content": "build\nnode_modules\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Microsoft\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "node-uwp\n==========\n\nEnables Universal Windows Platform (UWP) API access for Node.js (Chakra build)\non Windows 10.\n\nExample\n-------\n\n```javascript\nconst uwp = require('uwp');\nconst Windows = uwp.projectNamespace('Windows');\n\nWindows.Storage.KnownFolders.documentsLibrary.createFileAsync(\n  'sample.dat', Windows.Storage.CreationCollisionOption.replaceExisting)\n  .done(\n    function (file) {\n      console.log('ok');\n      uwp.close(); // all async operations are completed, release uwp\n    },\n    function (error) {\n      console.error('error', error);\n      uwp.close(); // all async operations are completed, release uwp\n    }\n);\n```\n\nInstallation\n------------\n\n### Prerequisites\n\n * Windows 10 [1511 or above](http://windows.microsoft.com/en-us/windows-10/windows-update-faq)\n * [Visual Studio](https://www.visualstudio.com/vs-2015-product-editions)\n * [Node.js (Chakra)](http://aka.ms/node-chakra-installer)\n\nRun under Node.js (Chakra) command prompt:\n\n```sh\nnpm install uwp\n```\n\nAPIs\n----\n\nThis package exports 2 functions.\n\n### projectNamespace(name)\n\nProject a UWP namespace of given name.\n\n* **Note**: This function will keep Node process alive so that your app can\n  continue to run and handle UWP async callbacks. You need to call\n  [close()](#close) when UWP usage is completed.\n\n<a name=\"close\"></a>\n### close()\n\nClose all UWP handles used by this package. Call this when all UWP usage is\ncompleted.\n\n---------------------------------------------------------------------------\nCheckout our OSS effort with\n[Node-ChakraCore](https://github.com/nodejs/node-chakracore). It supports the\nmost recent version of node.js and will also be useful if you are on Windows 7\nor Windows 8.1. Note: <b>It does not support UWP.</b>\n"
  },
  {
    "path": "SECURITY.md",
    "content": "<!-- BEGIN MICROSOFT SECURITY.MD V0.0.8 BLOCK -->\n\n## Security\n\nMicrosoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).\n\nIf you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.\n\n## Reporting Security Issues\n\n**Please do not report security vulnerabilities through public GitHub issues.**\n\nInstead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).\n\nIf you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com).  If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).\n\nYou should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). \n\nPlease include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:\n\n  * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)\n  * Full paths of source file(s) related to the manifestation of the issue\n  * The location of the affected source code (tag/branch/commit or direct URL)\n  * Any special configuration required to reproduce the issue\n  * Step-by-step instructions to reproduce the issue\n  * Proof-of-concept or exploit code (if possible)\n  * Impact of the issue, including how an attacker might exploit the issue\n\nThis information will help us triage your report more quickly.\n\nIf you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.\n\n## Preferred Languages\n\nWe prefer all communications to be in English.\n\n## Policy\n\nMicrosoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).\n\n<!-- END MICROSOFT SECURITY.MD BLOCK -->\n"
  },
  {
    "path": "binding.gyp",
    "content": "{\n  'targets': [{\n    'target_name': 'uwp',\n    \"include_dirs\" : [\n      \"<!(node -e \\\"require('nan')\\\")\"\n    ],\n    'sources': [\n      'binding.gyp',\n      'index.js',\n      'package.json',\n      'src/node-async.h',\n      'src/uwp.h',\n      'src/uwp.cc',\n    ],\n  }]\n}\n"
  },
  {
    "path": "index.js",
    "content": "// Copyright Microsoft. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and / or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\nconst uwp = module.exports = require('./build/release/uwp.node');\n\nconst nativeProjectNamespace = uwp.projectNamespace;\nuwp.projectNamespace = function(namespace) {\n  nativeProjectNamespace.call(uwp, namespace);\n  return namespace.split('.').reduce(function(prev, name) {\n    return prev[name];\n  }, global);\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"uwp\",\n  \"version\": \"1.0.2\",\n  \"description\": \"Enables Universal Windows Platform (UWP) API access for Node.js (Chakra build) on Windows 10.\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"install\": \"node-gyp rebuild\",\n    \"test\": \"node test/index.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/Microsoft/node-uwp.git\"\n  },\n  \"keywords\": [\n    \"uwp\",\n    \"node\",\n    \"node-uwp\",\n    \"jsrt\",\n    \"chakra\"\n  ],\n  \"author\": \"jianxu@microsoft.com\",\n  \"license\": \"MIT\",\n  \"gypfile\": true,\n  \"bugs\": {\n    \"url\": \"https://github.com/Microsoft/node-uwp/issues\"\n  },\n  \"homepage\": \"https://github.com/Microsoft/node-uwp#readme\",\n  \"dependencies\": {\n    \"nan\": \"^2.1.0\"\n  }\n}\n"
  },
  {
    "path": "src/node-async.h",
    "content": "// Copyright Microsoft. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and / or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\n#pragma once\n\n//\n// This file is derived from https://github.com/saary/node-async-helper\n//\n\n#include \"v8.h\"\n#include \"nan.h\"\n#include <thread>\n\nnamespace NodeUtils {\n\nextern std::thread::id g_mainThreadId;\n\nclass Async {\n private:\n  class TokenData {\n   private:\n    std::function<void()> func;\n    friend Async;\n\n   public:\n    static uv_async_t* NewAsyncToken() {\n      uv_async_t* asyncHandle = new uv_async_t;\n      uv_async_init(uv_default_loop(), asyncHandle, AsyncCb);\n      asyncHandle->data = new TokenData();\n\n      return asyncHandle;\n    }\n  };\n\n public:\n  static uv_async_t* GetAsyncToken() {\n    return TokenData::NewAsyncToken();\n  }\n\n  static void ReleaseAsyncToken(uv_async_t* handle) {\n    TokenData* tokenData = static_cast<TokenData*>(handle->data);\n    uv_close(reinterpret_cast<uv_handle_t*>(handle), AyncCloseCb);\n    delete tokenData;\n  }\n\n  static void RunOnMain(uv_async_t* async, std::function<void()> func) {\n    TokenData* tokenData = static_cast<TokenData*>(async->data);\n    tokenData->func = func;\n    uv_async_send(async);\n  }\n\n  static void RunOnMain(std::function<void()> func) {\n    if (std::this_thread::get_id() == g_mainThreadId) {\n      func();\n    } else {\n      uv_async_t *async = GetAsyncToken();\n      RunOnMain(async, func);\n    }\n  }\n\n private:\n  // called after the async handle is closed in order to free it's memory\n  static void AyncCloseCb(uv_handle_t* handle) {\n    if (handle != nullptr) {\n      uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);\n      delete async;\n    }\n  }\n\n  // Called by run on main in case we are not running on the main thread\n  static void AsyncCb(uv_async_t* handle) {\n    TokenData* tokenData = static_cast<TokenData*>(handle->data);\n    tokenData->func();\n    ReleaseAsyncToken(handle);\n  }\n};\n\n}  // namespace NodeUtils\n"
  },
  {
    "path": "src/uwp.cc",
    "content": "// Copyright Microsoft. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and / or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\n#include \"uwp.h\"\n\nstd::thread::id NodeUtils::g_mainThreadId;\nUWPAddOn UWPAddOn::s_instance;\n\nbool UWPAddOn::EnsureCoInitialized() {\n  if (!_coInitialized) {\n    HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);\n    _coInitialized = SUCCEEDED(hr);\n\n    if (!_coInitialized) {\n      Nan::ThrowError(\"CoInitializeEx failed\");\n    }\n  }\n\n  return _coInitialized;\n}\n\nvoid UWPAddOn::EnsureCoUninitialized() {\n  if (_coInitialized) {\n    CoUninitialize();\n    _coInitialized = false;\n  }\n}\n\nbool UWPAddOn::EnsureKeepAlive() {\n  if (_keepAliveToken == nullptr) {\n    // Open an active async handler to keep Node alive\n    _keepAliveToken = Async::GetAsyncToken();\n  }\n\n  return _keepAliveToken != nullptr;\n}\n\nvoid UWPAddOn::ReleaseKeepAlive() {\n  if (_keepAliveToken != nullptr) {\n    auto token = _keepAliveToken;\n    _keepAliveToken = nullptr;\n\n    Async::ReleaseAsyncToken(token);\n  }\n}\n\nvoid UWPAddOn::Init(Handle<Object> target) {\n  Nan::HandleScope scope;\n\n  NodeUtils::g_mainThreadId =\n    std::this_thread::get_id();  // Capture entering thread id\n\n  if (!s_instance.EnsureCoInitialized()) {\n    return;\n  }\n\n  JsErrorCode err = JsSetProjectionEnqueueCallback(\n    [](JsProjectionCallback jsCallback,\n       JsProjectionCallbackContext jsContext, void *context) {\n    Async::RunOnMain([jsCallback, jsContext]() {\n      jsCallback(jsContext);\n    });\n  },\n    /*projectionEnqueueContext*/nullptr);\n  if (err != JsNoError) {\n    Nan::ThrowError(\"JsSetProjectionEnqueueCallback failed\");\n    return;\n  }\n\n  Nan::SetMethod(target, \"projectNamespace\", ProjectNamespace);\n  Nan::SetMethod(target, \"close\", Close);\n}\n\nNAN_METHOD(UWPAddOn::ProjectNamespace) {\n  Nan::HandleScope scope;\n\n  if (!info[0]->IsString()) {\n    Nan::ThrowTypeError(\"Argument must be a string\");\n    return;\n  }\n\n  if (!s_instance.EnsureCoInitialized()) {\n    return;\n  }\n\n  String::Value name(info[0]);\n  if (JsProjectWinRTNamespace(reinterpret_cast<wchar_t*>(*name)) != JsNoError) {\n    Nan::ThrowError(\"JsProjectWinRTNamespace failed\");\n    return;\n  }\n\n  // Keep Node alive once successfully projected a UWP namespace\n  s_instance.EnsureKeepAlive();\n  return;\n}\n\nNAN_METHOD(UWPAddOn::Close) {\n  Nan::HandleScope scope;\n\n  s_instance.ReleaseKeepAlive();\n  s_instance.EnsureCoUninitialized();\n  return;\n}\n\nNODE_MODULE(uwp, UWPAddOn::Init);\n"
  },
  {
    "path": "src/uwp.h",
    "content": "// Copyright Microsoft. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and / or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\n#pragma once\n\n#include \"node-async.h\"\nusing namespace v8;\nusing NodeUtils::Async;\n\nclass UWPAddOn {\n private:\n  bool _coInitialized;\n  uv_async_t* _keepAliveToken;\n\n  static UWPAddOn s_instance;  // single instance\n\n  bool EnsureCoInitialized();\n  void EnsureCoUninitialized();\n  bool EnsureKeepAlive();\n  void ReleaseKeepAlive();\n\n public:\n  UWPAddOn()\n      : _coInitialized(false), _keepAliveToken(nullptr) {\n  }\n\n  static void Init(Handle<Object> target);\n  static NAN_METHOD(ProjectNamespace);\n  static NAN_METHOD(Close);\n};\n"
  },
  {
    "path": "test/index.js",
    "content": "// Copyright Microsoft. All rights reserved.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files(the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and / or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions :\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\nconst uwp = require('../index.js');\nconst Windows = uwp.projectNamespace('Windows');\n\nWindows.Storage.KnownFolders.documentsLibrary.createFileAsync(\n  'sample.dat', Windows.Storage.CreationCollisionOption.replaceExisting)\n  .done(\n    function (file) {\n      console.log('ok');\n      uwp.close(); // all async operations are completed, release uwp\n    },\n    function (error) {\n      console.error('error', error);\n      uwp.close(); // all async operations are completed, release uwp\n    }\n);\n"
  }
]