@ 260528.1

231103.1 · 7f4a9ed91bbecb84e39f4bc8030247ce5116ddf8

Reorganize examples into categorized folders (#341)

* refactor: create directory structure to organize exmaples
* test: update test_all to work with new directory structure
* fix: bug in test_all if no package.json scripts
* test: cleanup output of test_all
* fix: remove default test script that throws from thread_safe_function_with_object_wrap
* fix: remove build_with_cmake from .gitignore
* fix: swith to ' from " and remove subdir from getAllTests call
* test: add extra test cases for npm start and just running the pkgJson.main with node
* refactor: move all examples to src directory
* refactor: add numbers to categories so they are ordered in the src folder
* refactor: simplify getAllExamples in test_all.js
* docs: add directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure example in readme
* add back build_with_cmake --------- Co-authored-by: legendecas <legendecas@gmail.com>

reading declarations

.gitignore

@@ -1,5 +1,4 @@ build/-build_with_cmake/ node_modules/ Debug/ Release/

1_hello_world/README.md

deleted file mode 100644@@ -1,8 +0,0 @@-## Example 1: *Hello world*--To get started let's make a small addon which is the C++ equivalent of-the following JavaScript code:--```js-module.exports.hello = function() { return 'world'; };-```

1_hello_world/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "hello",-      "sources": [ "hello.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

1_hello_world/nan/hello.cc

deleted file mode 100644@@ -1,17 +0,0 @@-#include <nan.h>--void Method(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  info.GetReturnValue().Set(Nan::New("world").ToLocalChecked());-}--void Init(v8::Local<v8::Object> exports) {-  v8::Local<v8::Context> context =-      exports->GetCreationContext().ToLocalChecked();-  exports->Set(context,-               Nan::New("hello").ToLocalChecked(),-               Nan::New<v8::FunctionTemplate>(Method)-                   ->GetFunction(context)-                   .ToLocalChecked());-}--NODE_MODULE(hello, Init)

1_hello_world/nan/hello.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('hello');--console.log(addon.hello()); // 'world'\ No newline at end of file

1_hello_world/nan/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "hello_world",-  "version": "0.0.0",-  "description": "Node.js Addons Example #1",-  "main": "hello.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "nan": "^2.0.0"-  },-  "scripts": {-    "test": "node hello.js"-  },-  "gypfile": true-}

1_hello_world/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "hello",-      "sources": [ "hello.c" ]-    }-  ]-}

1_hello_world/napi/hello.c

deleted file mode 100644@@ -1,23 +0,0 @@-#include <assert.h>-#include <node_api.h>--static napi_value Method(napi_env env, napi_callback_info info) {-  napi_status status;-  napi_value world;-  status = napi_create_string_utf8(env, "world", 5, &world);-  assert(status == napi_ok);-  return world;-}--#define DECLARE_NAPI_METHOD(name, func)                                        \-  { name, 0, func, 0, 0, 0, napi_default, 0 }--static napi_value Init(napi_env env, napi_value exports) {-  napi_status status;-  napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);-  status = napi_define_properties(env, exports, 1, &desc);-  assert(status == napi_ok);-  return exports;-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

1_hello_world/napi/hello.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('hello');--console.log(addon.hello()); // 'world'

1_hello_world/napi/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "hello_world",-  "version": "0.0.0",-  "description": "Node.js Addons Example #1",-  "main": "hello.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1"-  },-  "scripts": {-    "test": "node hello.js"-  },-  "gypfile": true-}

1_hello_world/node-addon-api-addon-class/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "hello",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "hello.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': ['NAPI_DISABLE_CPP_EXCEPTIONS'],-    }-  ]-}

1_hello_world/node-addon-api-addon-class/hello.cc

deleted file mode 100644@@ -1,17 +0,0 @@-#include <napi.h>--class HelloAddon : public Napi::Addon<HelloAddon> {- public:-  HelloAddon(Napi::Env env, Napi::Object exports) {-    DefineAddon(exports, {-      InstanceMethod("hello", &HelloAddon::Hello, napi_enumerable)-    });-  }-- private:-  Napi::Value Hello(const Napi::CallbackInfo& info) {-    return Napi::String::New(info.Env(), "world");-  }-};--NODE_API_ADDON(HelloAddon)

1_hello_world/node-addon-api-addon-class/hello.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('hello');--console.log(addon.hello()); // 'world'

1_hello_world/node-addon-api-addon-class/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "hello_world",-  "version": "0.0.0",-  "description": "Node.js Addons Example #1",-  "main": "hello.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "node-addon-api": "^7.0.0"-  },-  "scripts": {-    "test": "node hello.js"-  },-  "gypfile": true-}

1_hello_world/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "hello",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "hello.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

1_hello_world/node-addon-api/hello.cc

deleted file mode 100644@@ -1,14 +0,0 @@-#include <napi.h>--Napi::String Method(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  return Napi::String::New(env, "world");-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "hello"),-              Napi::Function::New(env, Method));-  return exports;-}--NODE_API_MODULE(hello, Init)

1_hello_world/node-addon-api/hello.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('hello');--console.log(addon.hello()); // 'world'

1_hello_world/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "hello_world",-  "version": "0.0.0",-  "description": "Node.js Addons Example #1",-  "main": "hello.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "node-addon-api": "^1.0.0"-  },-  "scripts": {-    "test": "node hello.js"-  },-  "gypfile": true-}

2_function_arguments/README.md

deleted file mode 100644@@ -1,2 +0,0 @@-## Example 2: *Function arguments*-

2_function_arguments/nan/addon.cc

deleted file mode 100644@@ -1,33 +0,0 @@-#include <nan.h>--void Add(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();--  if (info.Length() < 2) {-    Nan::ThrowTypeError("Wrong number of arguments");-    return;-  }--  if (!info[0]->IsNumber() || !info[1]->IsNumber()) {-    Nan::ThrowTypeError("Wrong arguments");-    return;-  }--  double arg0 = info[0]->NumberValue(context).FromJust();-  double arg1 = info[1]->NumberValue(context).FromJust();-  v8::Local<v8::Number> num = Nan::New(arg0 + arg1);--  info.GetReturnValue().Set(num);-}--void Init(v8::Local<v8::Object> exports) {-  v8::Local<v8::Context> context =-      exports->GetCreationContext().ToLocalChecked();-  exports->Set(context,-               Nan::New("add").ToLocalChecked(),-               Nan::New<v8::FunctionTemplate>(Add)-                   ->GetFunction(context)-                   .ToLocalChecked());-}--NODE_MODULE(addon, Init)

2_function_arguments/nan/addon.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('addon.node')--console.log('This should be eight:', addon.add(3, 5))\ No newline at end of file

2_function_arguments/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

2_function_arguments/nan/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "function_arguments",-  "version": "0.0.0",-  "description": "Node.js Addons Example #2",-  "main": "addon.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "nan": "^2.0.0"-  },-  "scripts": {-    "test": "node addon.js"-  },-  "gypfile": true-}

2_function_arguments/napi/addon.c

deleted file mode 100644@@ -1,56 +0,0 @@-#include <assert.h>-#include <node_api.h>-#include <stdio.h>-static napi_value Add(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 2;-  napi_value args[2];-  status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);-  assert(status == napi_ok);--  if (argc < 2) {-    napi_throw_type_error(env, NULL, "Wrong number of arguments");-    return NULL;-  }--  napi_valuetype valuetype0;-  status = napi_typeof(env, args[0], &valuetype0);-  assert(status == napi_ok);--  napi_valuetype valuetype1;-  status = napi_typeof(env, args[1], &valuetype1);-  assert(status == napi_ok);--  if (valuetype0 != napi_number || valuetype1 != napi_number) {-    napi_throw_type_error(env, NULL, "Wrong arguments");-    return NULL;-  }--  double value0;-  status = napi_get_value_double(env, args[0], &value0);-  assert(status == napi_ok);--  double value1;-  status = napi_get_value_double(env, args[1], &value1);-  assert(status == napi_ok);--  napi_value sum;-  status = napi_create_double(env, value0 + value1, &sum);-  assert(status == napi_ok);--  return sum;-}--#define DECLARE_NAPI_METHOD(name, func)                                        \-  { name, 0, func, 0, 0, 0, napi_default, 0 }--napi_value Init(napi_env env, napi_value exports) {-  napi_status status;-  napi_property_descriptor addDescriptor = DECLARE_NAPI_METHOD("add", Add);-  status = napi_define_properties(env, exports, 1, &addDescriptor);-  assert(status == napi_ok);-  return exports;-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

2_function_arguments/napi/addon.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('addon.node')--console.log('This should be eight:', addon.add(3, 5))\ No newline at end of file

2_function_arguments/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.c" ]-    }-  ]-}

2_function_arguments/napi/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "function_arguments",-  "version": "0.0.0",-  "description": "Node.js Addons Example #2",-  "main": "addon.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1"-  },-  "scripts": {-    "test": "node addon.js"-  },-  "gypfile": true-}

2_function_arguments/node-addon-api/addon.cc

deleted file mode 100644@@ -1,29 +0,0 @@-#include <napi.h>--Napi::Value Add(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();--  if (info.Length() < 2) {-    Napi::TypeError::New(env, "Wrong number of arguments")-        .ThrowAsJavaScriptException();-    return env.Null();-  }--  if (!info[0].IsNumber() || !info[1].IsNumber()) {-    Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();-    return env.Null();-  }--  double arg0 = info[0].As<Napi::Number>().DoubleValue();-  double arg1 = info[1].As<Napi::Number>().DoubleValue();-  Napi::Number num = Napi::Number::New(env, arg0 + arg1);--  return num;-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "add"), Napi::Function::New(env, Add));-  return exports;-}--NODE_API_MODULE(addon, Init)

2_function_arguments/node-addon-api/addon.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('addon.node')--console.log('This should be eight:', addon.add(3, 5))

2_function_arguments/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

2_function_arguments/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "function_arguments",-  "version": "0.0.0",-  "description": "Node.js Addons Example #2",-  "main": "addon.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "node-addon-api": "^1.0.0"-  },-  "scripts": {-    "test": "node addon.js"-  },-  "gypfile": true-}

3_callbacks/nan/addon.cc

deleted file mode 100644@@ -1,15 +0,0 @@-#include <nan.h>--void RunCallback(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Function> cb = info[0].As<v8::Function>();-  const unsigned argc = 1;-  v8::Local<v8::Value> argv[argc] = {Nan::New("hello world").ToLocalChecked()};-  Nan::AsyncResource resource("nan:makeCallback");-  resource.runInAsyncScope(Nan::GetCurrentContext()->Global(), cb, argc, argv);-}--void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {-  Nan::SetMethod(module, "exports", RunCallback);-}--NODE_MODULE(addon, Init)

3_callbacks/nan/addon.js

deleted file mode 100644@@ -1,5 +0,0 @@-var addon = require('bindings')('addon');--addon(function(msg){-  console.log(msg); // 'hello world'-});\ No newline at end of file

3_callbacks/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

3_callbacks/nan/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "callbacks",-  "version": "0.0.0",-  "description": "Node.js Addons Example #3",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "nan": "^2.14.0"-  }-}

3_callbacks/napi/addon.c

deleted file mode 100644@@ -1,37 +0,0 @@-#include <assert.h>-#include <node_api.h>--static napi_value RunCallback(napi_env env, const napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value args[1];-  status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);-  assert(status == napi_ok);--  napi_value cb = args[0];--  napi_value argv[1];-  status = napi_create_string_utf8(env, "hello world", NAPI_AUTO_LENGTH, argv);-  assert(status == napi_ok);--  napi_value global;-  status = napi_get_global(env, &global);-  assert(status == napi_ok);--  napi_value result;-  status = napi_call_function(env, global, cb, 1, argv, &result);-  assert(status == napi_ok);--  return NULL;-}--static napi_value Init(napi_env env, napi_value exports) {-  napi_value new_exports;-  napi_status status = napi_create_function(-      env, "", NAPI_AUTO_LENGTH, RunCallback, NULL, &new_exports);-  assert(status == napi_ok);-  return new_exports;-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

3_callbacks/napi/addon.js

deleted file mode 100644@@ -1,5 +0,0 @@-var addon = require('bindings')('addon');--addon(function(msg){-  console.log(msg); // 'hello world'-});

3_callbacks/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.c" ]-    }-  ]-}

3_callbacks/napi/package.json

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "name": "napi_callbacks",-  "version": "0.0.0",-  "description": "Node.js Addons Example #3",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.2.1"-  }-}

3_callbacks/node-addon-api/addon.cc

deleted file mode 100644@@ -1,13 +0,0 @@-#include <napi.h>--void RunCallback(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  Napi::Function cb = info[0].As<Napi::Function>();-  cb.Call(env.Global(), {Napi::String::New(env, "hello world")});-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  return Napi::Function::New(env, RunCallback);-}--NODE_API_MODULE(addon, Init)

3_callbacks/node-addon-api/addon.js

deleted file mode 100644@@ -1,5 +0,0 @@-var addon = require('bindings')('addon');--addon(function(msg){-  console.log(msg); // 'hello world'-});

3_callbacks/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

3_callbacks/node-addon-api/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "callbacks",-  "version": "0.0.0",-  "description": "Node.js Addons Example #3",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "node-addon-api": "^1.0.0"-  }-}

4_object_factory/nan/addon.cc

deleted file mode 100644@@ -1,23 +0,0 @@-#include <nan.h>--void CreateObject(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();-  v8::Local<v8::Object> obj = Nan::New<v8::Object>();-  obj->Set(context,-           Nan::New("msg").ToLocalChecked(),-           info[0]->ToString(context).ToLocalChecked());--  info.GetReturnValue().Set(obj);-}--void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {-  v8::Local<v8::Context> context =-      exports->GetCreationContext().ToLocalChecked();-  module->Set(context,-              Nan::New("exports").ToLocalChecked(),-              Nan::New<v8::FunctionTemplate>(CreateObject)-                  ->GetFunction(context)-                  .ToLocalChecked());-}--NODE_MODULE(addon, Init)

4_object_factory/nan/addon.js

deleted file mode 100644@@ -1,5 +0,0 @@-var addon = require('bindings')('addon');--var obj1 = addon('hello');-var obj2 = addon('world');-console.log(obj1.msg+' '+obj2.msg); // 'hello world'\ No newline at end of file

4_object_factory/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

4_object_factory/nan/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "object_factory",-  "version": "0.0.0",-  "description": "Node.js Addons Example #4",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "nan": "^2.14.0"-  }-}

4_object_factory/napi/addon.c

deleted file mode 100644@@ -1,30 +0,0 @@-#include <assert.h>-#include <node_api.h>--static napi_value CreateObject(napi_env env, const napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value args[1];-  status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);-  assert(status == napi_ok);--  napi_value obj;-  status = napi_create_object(env, &obj);-  assert(status == napi_ok);--  status = napi_set_named_property(env, obj, "msg", args[0]);-  assert(status == napi_ok);--  return obj;-}--static napi_value Init(napi_env env, napi_value exports) {-  napi_value new_exports;-  napi_status status = napi_create_function(-      env, "", NAPI_AUTO_LENGTH, CreateObject, NULL, &new_exports);-  assert(status == napi_ok);-  return new_exports;-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

4_object_factory/napi/addon.js

deleted file mode 100644@@ -1,5 +0,0 @@-var addon = require('bindings')('addon');--var obj1 = addon('hello');-var obj2 = addon('world');-console.log(obj1.msg+' '+obj2.msg); // 'hello world'

4_object_factory/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.c" ]-    }-  ]-}

4_object_factory/napi/package.json

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "name": "object_factory",-  "version": "0.0.0",-  "description": "Node.js Addons Example #4",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.2.1"-  }-}

4_object_factory/node-addon-api/addon.cc

deleted file mode 100644@@ -1,15 +0,0 @@-#include <napi.h>--Napi::Object CreateObject(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  Napi::Object obj = Napi::Object::New(env);-  obj.Set(Napi::String::New(env, "msg"), info[0].ToString());--  return obj;-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  return Napi::Function::New(env, CreateObject, "createObject");-}--NODE_API_MODULE(addon, Init)

4_object_factory/node-addon-api/addon.js

deleted file mode 100644@@ -1,5 +0,0 @@-var addon = require('bindings')('addon');--var obj1 = addon('hello');-var obj2 = addon('world');-console.log(obj1.msg+' '+obj2.msg); // 'hello world'\ No newline at end of file

4_object_factory/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

4_object_factory/node-addon-api/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "object_factory",-  "version": "0.0.0",-  "description": "Node.js Addons Example #4",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "node-addon-api": "^1.0.0"-  }-}

5_function_factory/nan/addon.cc

deleted file mode 100644@@ -1,23 +0,0 @@-#include <nan.h>--void MyFunction(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  info.GetReturnValue().Set(Nan::New("hello world").ToLocalChecked());-}--void CreateFunction(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();-  v8::Local<v8::FunctionTemplate> tpl =-      Nan::New<v8::FunctionTemplate>(MyFunction);-  v8::Local<v8::Function> fn = tpl->GetFunction(context).ToLocalChecked();--  // omit this to make it anonymous-  fn->SetName(Nan::New("theFunction").ToLocalChecked());--  info.GetReturnValue().Set(fn);-}--void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {-  Nan::SetMethod(module, "exports", CreateFunction);-}--NODE_MODULE(addon, Init)

5_function_factory/nan/addon.js

deleted file mode 100644@@ -1,4 +0,0 @@-var addon = require('bindings')('addon');--var fn = addon();-console.log(fn()); // 'hello world'\ No newline at end of file

5_function_factory/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

5_function_factory/nan/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "function_factory",-  "version": "0.0.0",-  "description": "Node.js Addons Example #5",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "nan": "^2.0.0"-  }-}

5_function_factory/napi/addon.c

deleted file mode 100644@@ -1,33 +0,0 @@-#include <node_api.h>-#include <assert.h>--static napi_value MyFunction(napi_env env, napi_callback_info info) {-  napi_status status;--  napi_value str;-  status = napi_create_string_utf8(env, "hello world", NAPI_AUTO_LENGTH, &str);-  assert(status == napi_ok);--  return str;-}--static napi_value CreateFunction(napi_env env, napi_callback_info info) {-  napi_status status;--  napi_value fn;-  status = napi_create_function(-      env, "theFunction", NAPI_AUTO_LENGTH, MyFunction, NULL, &fn);-  assert(status == napi_ok);--  return fn;-}--static napi_value Init(napi_env env, napi_value exports) {-  napi_value new_exports;-  napi_status status = napi_create_function(-      env, "", NAPI_AUTO_LENGTH, CreateFunction, NULL, &new_exports);-  assert(status == napi_ok);-  return new_exports;-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

5_function_factory/napi/addon.js

deleted file mode 100644@@ -1,4 +0,0 @@-var addon = require('bindings')('addon');--var fn = addon();-console.log(fn()); // 'hello world'

5_function_factory/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.c" ]-    }-  ]-}

5_function_factory/napi/package.json

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "name": "function_factory",-  "version": "0.0.0",-  "description": "Node.js Addons Example #5",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0"-  }-}

5_function_factory/node-addon-api/addon.cc

deleted file mode 100644@@ -1,18 +0,0 @@-#include <napi.h>--Napi::String MyFunction(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  return Napi::String::New(env, "hello world");-}--Napi::Function CreateFunction(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  Napi::Function fn = Napi::Function::New(env, MyFunction, "theFunction");-  return fn;-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  return Napi::Function::New(env, CreateFunction, "createObject");-}--NODE_API_MODULE(addon, Init)

5_function_factory/node-addon-api/addon.js

deleted file mode 100644@@ -1,4 +0,0 @@-var addon = require('bindings')('addon');--var fn = addon();-console.log(fn()); // 'hello world'

5_function_factory/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "addon.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

5_function_factory/node-addon-api/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "function_factory",-  "version": "0.0.0",-  "description": "Node.js Addons Example #5",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "node-addon-api": "^7.0.0"-  }-}

6_object_wrap/nan/addon.cc

deleted file mode 100644@@ -1,8 +0,0 @@-#include <nan.h>-#include "myobject.h"--void InitAll(v8::Local<v8::Object> exports) {-  MyObject::Init(exports);-}--NODE_MODULE(addon, InitAll)

6_object_wrap/nan/addon.js

deleted file mode 100644@@ -1,13 +0,0 @@-var addon = require('bindings')('addon');--var obj = new addon.MyObject(10);-console.log( obj.plusOne() ); // 11-console.log( obj.plusOne() ); // 12-console.log( obj.plusOne() ); // 13--console.log( obj.multiply().value() ); // 13-console.log( obj.multiply(10).value() ); // 130--var newobj = obj.multiply(-1);-console.log( newobj.value() ); // -13-console.log( obj === newobj ); // false

6_object_wrap/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc", "myobject.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

6_object_wrap/nan/myobject.cc

deleted file mode 100644@@ -1,73 +0,0 @@-#include "myobject.h"--Nan::Persistent<v8::Function> MyObject::constructor;--MyObject::MyObject(double value) : value_(value) {}--MyObject::~MyObject() {}--void MyObject::Init(v8::Local<v8::Object> exports) {-  v8::Local<v8::Context> context =-      exports->GetCreationContext().ToLocalChecked();-  Nan::HandleScope scope;--  // Prepare constructor template-  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);-  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());-  tpl->InstanceTemplate()->SetInternalFieldCount(1);--  // Prototype-  Nan::SetPrototypeMethod(tpl, "value", GetValue);-  Nan::SetPrototypeMethod(tpl, "plusOne", PlusOne);-  Nan::SetPrototypeMethod(tpl, "multiply", Multiply);--  constructor.Reset(tpl->GetFunction(context).ToLocalChecked());-  exports->Set(context,-               Nan::New("MyObject").ToLocalChecked(),-               tpl->GetFunction(context).ToLocalChecked());-}--void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();-  if (info.IsConstructCall()) {-    // Invoked as constructor: `new MyObject(...)`-    double value =-        info[0]->IsUndefined() ? 0 : info[0]->NumberValue(context).FromJust();-    MyObject* obj = new MyObject(value);-    obj->Wrap(info.This());-    info.GetReturnValue().Set(info.This());-  } else {-    // Invoked as plain function `MyObject(...)`, turn into construct call.-    const int argc = 1;-    v8::Local<v8::Value> argv[argc] = {info[0]};-    v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);-    info.GetReturnValue().Set(-        cons->NewInstance(context, argc, argv).ToLocalChecked());-  }-}--void MyObject::GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());-  info.GetReturnValue().Set(Nan::New(obj->value_));-}--void MyObject::PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());-  obj->value_ += 1;-  info.GetReturnValue().Set(Nan::New(obj->value_));-}--void MyObject::Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();-  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());-  double multiple =-      info[0]->IsUndefined() ? 1 : info[0]->NumberValue(context).FromJust();--  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);--  const int argc = 1;-  v8::Local<v8::Value> argv[argc] = {Nan::New(obj->value_ * multiple)};--  info.GetReturnValue().Set(-      cons->NewInstance(context, argc, argv).ToLocalChecked());-}

6_object_wrap/nan/myobject.h

deleted file mode 100644@@ -1,22 +0,0 @@-#ifndef MYOBJECT_H-#define MYOBJECT_H--#include <nan.h>--class MyObject : public Nan::ObjectWrap {- public:-  static void Init(v8::Local<v8::Object> exports);-- private:-  explicit MyObject(double value = 0);-  ~MyObject();--  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);-  static void GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info);-  static void PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info);-  static void Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info);-  static Nan::Persistent<v8::Function> constructor;-  double value_;-};--#endif

6_object_wrap/nan/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "object_wrap",-  "version": "0.0.0",-  "description": "Node.js Addons Example #6",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "nan": "^2.14.0"-  }-}

6_object_wrap/napi/addon.cc

deleted file mode 100644@@ -1,7 +0,0 @@-#include "myobject.h"--napi_value Init(napi_env env, napi_value exports) {-  return MyObject::Init(env, exports);-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

6_object_wrap/napi/addon.js

deleted file mode 100644@@ -1,13 +0,0 @@-var addon = require('bindings')('addon');--var obj = new addon.MyObject(10);-console.log( obj.plusOne() ); // 11-console.log( obj.plusOne() ); // 12-console.log( obj.plusOne() ); // 13--console.log( obj.multiply().value ); // 13-console.log( obj.multiply(10).value ); // 130--var newobj = obj.multiply(-1);-console.log( newobj.value ); // -13-console.log( obj === newobj ); // false

6_object_wrap/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc", "myobject.cc" ]-    }-  ]-}

6_object_wrap/napi/myobject.cc

deleted file mode 100644@@ -1,223 +0,0 @@-#include "myobject.h"-#include <assert.h>--MyObject::MyObject(double value)-    : value_(value), env_(nullptr), wrapper_(nullptr) {}--MyObject::~MyObject() {-  napi_delete_reference(env_, wrapper_);-}--void MyObject::Destructor(napi_env env,-                          void* nativeObject,-                          void* /*finalize_hint*/) {-  reinterpret_cast<MyObject*>(nativeObject)->~MyObject();-}--#define DECLARE_NAPI_METHOD(name, func)                                        \-  { name, 0, func, 0, 0, 0, napi_default, 0 }--napi_value MyObject::Init(napi_env env, napi_value exports) {-  napi_status status;-  napi_property_descriptor properties[] = {-      {"value", 0, 0, GetValue, SetValue, 0, napi_default, 0},-      DECLARE_NAPI_METHOD("plusOne", PlusOne),-      DECLARE_NAPI_METHOD("multiply", Multiply),-  };--  napi_value cons;-  status = napi_define_class(-      env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 3, properties, &cons);-  assert(status == napi_ok);--  // We will need the constructor `cons` later during the life cycle of the-  // addon, so we store a persistent reference to it as the instance data for-  // our addon. This will enable us to use `napi_get_instance_data` at any-  // point during the life cycle of our addon to retrieve it. We cannot simply-  // store it as a global static variable, because that will render our addon-  // unable to support Node.js worker threads and multiple contexts on a single-  // thread.-  //-  // The finalizer we pass as a lambda will be called when our addon is unloaded-  // and is responsible for releasing the persistent reference and freeing the-  // heap memory where we stored the persistent reference.-  napi_ref* constructor = new napi_ref;-  status = napi_create_reference(env, cons, 1, constructor);-  assert(status == napi_ok);-  status = napi_set_instance_data(-      env,-      constructor,-      [](napi_env env, void* data, void* hint) {-        napi_ref* constructor = static_cast<napi_ref*>(data);-        napi_status status = napi_delete_reference(env, *constructor);-        assert(status == napi_ok);-        delete constructor;-      },-      nullptr);-  assert(status == napi_ok);--  status = napi_set_named_property(env, exports, "MyObject", cons);-  assert(status == napi_ok);-  return exports;-}--napi_value MyObject::Constructor(napi_env env) {-  void* instance_data = nullptr;-  napi_status status = napi_get_instance_data(env, &instance_data);-  assert(status == napi_ok);-  napi_ref* constructor = static_cast<napi_ref*>(instance_data);--  napi_value cons;-  status = napi_get_reference_value(env, *constructor, &cons);-  assert(status == napi_ok);-  return cons;-}--napi_value MyObject::New(napi_env env, napi_callback_info info) {-  napi_status status;--  napi_value target;-  status = napi_get_new_target(env, info, &target);-  assert(status == napi_ok);-  bool is_constructor = target != nullptr;--  if (is_constructor) {-    // Invoked as constructor: `new MyObject(...)`-    size_t argc = 1;-    napi_value args[1];-    napi_value jsthis;-    status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);-    assert(status == napi_ok);--    double value = 0;--    napi_valuetype valuetype;-    status = napi_typeof(env, args[0], &valuetype);-    assert(status == napi_ok);--    if (valuetype != napi_undefined) {-      status = napi_get_value_double(env, args[0], &value);-      assert(status == napi_ok);-    }--    MyObject* obj = new MyObject(value);--    obj->env_ = env;-    status = napi_wrap(env,-                       jsthis,-                       reinterpret_cast<void*>(obj),-                       MyObject::Destructor,-                       nullptr,  // finalize_hint-                       &obj->wrapper_);-    assert(status == napi_ok);--    return jsthis;-  } else {-    // Invoked as plain function `MyObject(...)`, turn into construct call.-    size_t argc_ = 1;-    napi_value args[1];-    status = napi_get_cb_info(env, info, &argc_, args, nullptr, nullptr);-    assert(status == napi_ok);--    const size_t argc = 1;-    napi_value argv[argc] = {args[0]};--    napi_value instance;-    status = napi_new_instance(env, Constructor(env), argc, argv, &instance);-    assert(status == napi_ok);--    return instance;-  }-}--napi_value MyObject::GetValue(napi_env env, napi_callback_info info) {-  napi_status status;--  napi_value jsthis;-  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);-  assert(status == napi_ok);--  MyObject* obj;-  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));-  assert(status == napi_ok);--  napi_value num;-  status = napi_create_double(env, obj->value_, &num);-  assert(status == napi_ok);--  return num;-}--napi_value MyObject::SetValue(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value value;-  napi_value jsthis;-  status = napi_get_cb_info(env, info, &argc, &value, &jsthis, nullptr);-  assert(status == napi_ok);--  MyObject* obj;-  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));-  assert(status == napi_ok);--  status = napi_get_value_double(env, value, &obj->value_);-  assert(status == napi_ok);--  return nullptr;-}--napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {-  napi_status status;--  napi_value jsthis;-  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);-  assert(status == napi_ok);--  MyObject* obj;-  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));-  assert(status == napi_ok);--  obj->value_ += 1;--  napi_value num;-  status = napi_create_double(env, obj->value_, &num);-  assert(status == napi_ok);--  return num;-}--napi_value MyObject::Multiply(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value args[1];-  napi_value jsthis;-  status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);-  assert(status == napi_ok);--  napi_valuetype valuetype;-  status = napi_typeof(env, args[0], &valuetype);-  assert(status == napi_ok);--  double multiple = 1;-  if (valuetype != napi_undefined) {-    status = napi_get_value_double(env, args[0], &multiple);-    assert(status == napi_ok);-  }--  MyObject* obj;-  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));-  assert(status == napi_ok);--  const int kArgCount = 1;-  napi_value argv[kArgCount];-  status = napi_create_double(env, obj->value_ * multiple, argv);-  assert(status == napi_ok);--  napi_value instance;-  status = napi_new_instance(env, Constructor(env), kArgCount, argv, &instance);-  assert(status == napi_ok);--  return instance;-}

6_object_wrap/napi/myobject.h

deleted file mode 100644@@ -1,27 +0,0 @@-#ifndef TEST_ADDONS_NAPI_6_OBJECT_WRAP_MYOBJECT_H_-#define TEST_ADDONS_NAPI_6_OBJECT_WRAP_MYOBJECT_H_--#include <node_api.h>--class MyObject {- public:-  static napi_value Init(napi_env env, napi_value exports);-  static void Destructor(napi_env env, void* nativeObject, void* finalize_hint);-- private:-  explicit MyObject(double value_ = 0);-  ~MyObject();--  static napi_value New(napi_env env, napi_callback_info info);-  static napi_value GetValue(napi_env env, napi_callback_info info);-  static napi_value SetValue(napi_env env, napi_callback_info info);-  static napi_value PlusOne(napi_env env, napi_callback_info info);-  static napi_value Multiply(napi_env env, napi_callback_info info);-  static inline napi_value Constructor(napi_env env);--  double value_;-  napi_env env_;-  napi_ref wrapper_;-};--#endif  // TEST_ADDONS_NAPI_6_OBJECT_WRAP_MYOBJECT_H_

6_object_wrap/napi/package.json

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "name": "object_wrap",-  "version": "0.0.0",-  "description": "Node.js Addons Example #6",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0"-  }-}

6_object_wrap/node-addon-api/addon.cc

deleted file mode 100644@@ -1,8 +0,0 @@-#include <napi.h>-#include "myobject.h"--Napi::Object InitAll(Napi::Env env, Napi::Object exports) {-  return MyObject::Init(env, exports);-}--NODE_API_MODULE(addon, InitAll)

6_object_wrap/node-addon-api/addon.js

deleted file mode 100644@@ -1,13 +0,0 @@-var addon = require('bindings')('addon');--var obj = new addon.MyObject(10);-console.log( obj.plusOne() ); // 11-console.log( obj.plusOne() ); // 12-console.log( obj.plusOne() ); // 13--console.log( obj.multiply().value() ); // 13-console.log( obj.multiply(10).value() ); // 130--var newobj = obj.multiply(-1);-console.log( newobj.value() ); // -13-console.log( obj === newobj ); // false

6_object_wrap/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "addon.cc", "myobject.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

6_object_wrap/node-addon-api/myobject.cc

deleted file mode 100644@@ -1,58 +0,0 @@-#include "myobject.h"--Napi::Object MyObject::Init(Napi::Env env, Napi::Object exports) {-  Napi::Function func =-      DefineClass(env,-                  "MyObject",-                  {InstanceMethod("plusOne", &MyObject::PlusOne),-                   InstanceMethod("value", &MyObject::GetValue),-                   InstanceMethod("multiply", &MyObject::Multiply)});--  Napi::FunctionReference* constructor = new Napi::FunctionReference();-  *constructor = Napi::Persistent(func);-  env.SetInstanceData(constructor);--  exports.Set("MyObject", func);-  return exports;-}--MyObject::MyObject(const Napi::CallbackInfo& info)-    : Napi::ObjectWrap<MyObject>(info) {-  Napi::Env env = info.Env();--  int length = info.Length();--  if (length <= 0 || !info[0].IsNumber()) {-    Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();-    return;-  }--  Napi::Number value = info[0].As<Napi::Number>();-  this->value_ = value.DoubleValue();-}--Napi::Value MyObject::GetValue(const Napi::CallbackInfo& info) {-  double num = this->value_;--  return Napi::Number::New(info.Env(), num);-}--Napi::Value MyObject::PlusOne(const Napi::CallbackInfo& info) {-  this->value_ = this->value_ + 1;--  return MyObject::GetValue(info);-}--Napi::Value MyObject::Multiply(const Napi::CallbackInfo& info) {-  Napi::Number multiple;-  if (info.Length() <= 0 || !info[0].IsNumber()) {-    multiple = Napi::Number::New(info.Env(), 1);-  } else {-    multiple = info[0].As<Napi::Number>();-  }--  Napi::Object obj = info.Env().GetInstanceData<Napi::FunctionReference>()->New(-      {Napi::Number::New(info.Env(), this->value_ * multiple.DoubleValue())});--  return obj;-}

6_object_wrap/node-addon-api/myobject.h

deleted file mode 100644@@ -1,19 +0,0 @@-#ifndef MYOBJECT_H-#define MYOBJECT_H--#include <napi.h>--class MyObject : public Napi::ObjectWrap<MyObject> {- public:-  static Napi::Object Init(Napi::Env env, Napi::Object exports);-  MyObject(const Napi::CallbackInfo& info);-- private:-  Napi::Value GetValue(const Napi::CallbackInfo& info);-  Napi::Value PlusOne(const Napi::CallbackInfo& info);-  Napi::Value Multiply(const Napi::CallbackInfo& info);--  double value_;-};--#endif

6_object_wrap/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "object_wrap",-  "version": "0.0.0",-  "description": "Node.js Addons Example #6",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "engines": {-    "node": "~10 >=10.20 || >=12.17"-  },-  "dependencies": {-    "bindings": "~1.5.0",-    "node-addon-api": "^3.0.0"-  }-}

7_factory_wrap/nan/addon.cc

deleted file mode 100644@@ -1,23 +0,0 @@-#include <nan.h>-#include "myobject.h"--void CreateObject(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  info.GetReturnValue().Set(MyObject::NewInstance(info[0]));-}--void InitAll(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {-  v8::Local<v8::Context> context =-      exports->GetCreationContext().ToLocalChecked();--  Nan::HandleScope scope;--  MyObject::Init();--  module->Set(context,-              Nan::New("exports").ToLocalChecked(),-              Nan::New<v8::FunctionTemplate>(CreateObject)-                  ->GetFunction(context)-                  .ToLocalChecked());-}--NODE_MODULE(addon, InitAll)

7_factory_wrap/nan/addon.js

deleted file mode 100644@@ -1,11 +0,0 @@-var createObject = require('bindings')('addon');--var obj = createObject(10);-console.log( obj.plusOne() ); // 11-console.log( obj.plusOne() ); // 12-console.log( obj.plusOne() ); // 13--var obj2 = createObject(20);-console.log( obj2.plusOne() ); // 21-console.log( obj2.plusOne() ); // 22-console.log( obj2.plusOne() ); // 23

7_factory_wrap/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc", "myobject.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

7_factory_wrap/nan/myobject.cc

deleted file mode 100644@@ -1,56 +0,0 @@-#include "myobject.h"-#include <nan.h>--using namespace v8;--MyObject::MyObject(){};-MyObject::~MyObject(){};--Nan::Persistent<v8::Function> MyObject::constructor;--void MyObject::Init() {-  Nan::HandleScope scope;--  // Prepare constructor template-  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);-  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());-  tpl->InstanceTemplate()->SetInternalFieldCount(1);-  // Prototype-  tpl->PrototypeTemplate()->Set(Nan::New("plusOne").ToLocalChecked(),-                                Nan::New<v8::FunctionTemplate>(PlusOne));--  constructor.Reset(-      tpl->GetFunction(Nan::GetCurrentContext()).ToLocalChecked());-}--void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();--  MyObject* obj = new MyObject();-  obj->counter_ =-      info[0]->IsUndefined() ? 0 : info[0]->NumberValue(context).FromJust();-  obj->Wrap(info.This());--  info.GetReturnValue().Set(info.This());-}--v8::Local<v8::Object> MyObject::NewInstance(v8::Local<v8::Value> arg) {-  Nan::EscapableHandleScope scope;--  const unsigned argc = 1;-  v8::Local<v8::Value> argv[argc] = {arg};-  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);-  v8::Local<v8::Context> context =-      v8::Isolate::GetCurrent()->GetCurrentContext();-  v8::Local<v8::Object> instance =-      cons->NewInstance(context, argc, argv).ToLocalChecked();--  return scope.Escape(instance);-}--void MyObject::PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.This());-  obj->counter_ += 1;--  info.GetReturnValue().Set(Nan::New(obj->counter_));-}

7_factory_wrap/nan/myobject.h

deleted file mode 100644@@ -1,21 +0,0 @@-#ifndef MYOBJECT_H-#define MYOBJECT_H--#include <nan.h>--class MyObject : public Nan::ObjectWrap {- public:-  static void Init();-  static v8::Local<v8::Object> NewInstance(v8::Local<v8::Value> arg);-- private:-  MyObject();-  ~MyObject();--  static Nan::Persistent<v8::Function> constructor;-  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);-  static void PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info);-  double counter_;-};--#endif

7_factory_wrap/nan/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "factory_wrap",-  "version": "0.0.0",-  "description": "Node.js Addons Example #7",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "nan": "^2.0.0"-  }-}

7_factory_wrap/napi/addon.cc

deleted file mode 100644@@ -1,30 +0,0 @@-#include <assert.h>-#include "myobject.h"--napi_value CreateObject(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value args[1];-  status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);-  assert(status == napi_ok);--  napi_value instance;-  status = MyObject::NewInstance(env, args[0], &instance);-  assert(status == napi_ok);--  return instance;-}--napi_value Init(napi_env env, napi_value exports) {-  napi_status status = MyObject::Init(env);-  assert(status == napi_ok);--  napi_value new_exports;-  status = napi_create_function(-      env, "", NAPI_AUTO_LENGTH, CreateObject, nullptr, &new_exports);-  assert(status == napi_ok);-  return new_exports;-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

7_factory_wrap/napi/addon.js

deleted file mode 100644@@ -1,11 +0,0 @@-var createObject = require('bindings')('addon');--var obj = createObject(10);-console.log( obj.plusOne() ); // 11-console.log( obj.plusOne() ); // 12-console.log( obj.plusOne() ); // 13--var obj2 = createObject(20);-console.log( obj2.plusOne() ); // 21-console.log( obj2.plusOne() ); // 22-console.log( obj2.plusOne() ); // 23

7_factory_wrap/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc", "myobject.cc" ]-    }-  ]-}

7_factory_wrap/napi/myobject.cc

deleted file mode 100644@@ -1,137 +0,0 @@-#include "myobject.h"-#include <assert.h>--MyObject::MyObject() : env_(nullptr), wrapper_(nullptr) {}--MyObject::~MyObject() {-  napi_delete_reference(env_, wrapper_);-}--void MyObject::Destructor(napi_env env,-                          void* nativeObject,-                          void* /*finalize_hint*/) {-  reinterpret_cast<MyObject*>(nativeObject)->~MyObject();-}--#define DECLARE_NAPI_METHOD(name, func)                                        \-  { name, 0, func, 0, 0, 0, napi_default, 0 }--napi_status MyObject::Init(napi_env env) {-  napi_status status;-  napi_property_descriptor properties[] = {-      DECLARE_NAPI_METHOD("plusOne", PlusOne),-  };--  napi_value cons;-  status = napi_define_class(-      env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 1, properties, &cons);-  if (status != napi_ok) return status;--  // We will need the constructor `cons` later during the life cycle of the-  // addon, so we store a persistent reference to it as the instance data for-  // our addon. This will enable us to use `napi_get_instance_data` at any-  // point during the life cycle of our addon to retrieve it. We cannot simply-  // store it as a global static variable, because that will render our addon-  // unable to support Node.js worker threads and multiple contexts on a single-  // thread.-  //-  // The finalizer we pass as a lambda will be called when our addon is unloaded-  // and is responsible for releasing the persistent reference and freeing the-  // heap memory where we stored the persistent reference.-  napi_ref* constructor = new napi_ref;-  status = napi_create_reference(env, cons, 1, constructor);-  assert(status == napi_ok);-  status = napi_set_instance_data(-      env,-      constructor,-      [](napi_env env, void* data, void* hint) {-        napi_ref* constructor = static_cast<napi_ref*>(data);-        napi_status status = napi_delete_reference(env, *constructor);-        assert(status == napi_ok);-        delete constructor;-      },-      nullptr);-  assert(status == napi_ok);--  return napi_ok;-}--napi_value MyObject::New(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value args[1];-  napi_value jsthis;-  status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);-  assert(status == napi_ok);--  napi_valuetype valuetype;-  status = napi_typeof(env, args[0], &valuetype);-  assert(status == napi_ok);--  MyObject* obj = new MyObject();--  if (valuetype == napi_undefined) {-    obj->counter_ = 0;-  } else {-    status = napi_get_value_double(env, args[0], &obj->counter_);-    assert(status == napi_ok);-  }--  obj->env_ = env;-  status = napi_wrap(env,-                     jsthis,-                     reinterpret_cast<void*>(obj),-                     MyObject::Destructor,-                     nullptr, /* finalize_hint */-                     &obj->wrapper_);-  assert(status == napi_ok);--  return jsthis;-}--napi_value MyObject::Constructor(napi_env env) {-  void* instance_data = nullptr;-  napi_status status = napi_get_instance_data(env, &instance_data);-  assert(status == napi_ok);-  napi_ref* constructor = static_cast<napi_ref*>(instance_data);--  napi_value cons;-  status = napi_get_reference_value(env, *constructor, &cons);-  assert(status == napi_ok);-  return cons;-}--napi_status MyObject::NewInstance(napi_env env,-                                  napi_value arg,-                                  napi_value* instance) {-  napi_status status;--  const int argc = 1;-  napi_value argv[argc] = {arg};--  status = napi_new_instance(env, Constructor(env), argc, argv, instance);-  if (status != napi_ok) return status;--  return napi_ok;-}--napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {-  napi_status status;--  napi_value jsthis;-  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);-  assert(status == napi_ok);--  MyObject* obj;-  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));-  assert(status == napi_ok);--  obj->counter_ += 1;--  napi_value num;-  status = napi_create_double(env, obj->counter_, &num);-  assert(status == napi_ok);--  return num;-}

7_factory_wrap/napi/myobject.h

deleted file mode 100644@@ -1,26 +0,0 @@-#ifndef TEST_ADDONS_NAPI_7_FACTORY_WRAP_MYOBJECT_H_-#define TEST_ADDONS_NAPI_7_FACTORY_WRAP_MYOBJECT_H_--#include <node_api.h>--class MyObject {- public:-  static napi_status Init(napi_env env);-  static void Destructor(napi_env env, void* nativeObject, void* finalize_hint);-  static napi_status NewInstance(napi_env env,-                                 napi_value arg,-                                 napi_value* instance);-- private:-  MyObject();-  ~MyObject();--  static inline napi_value Constructor(napi_env env);-  static napi_value New(napi_env env, napi_callback_info info);-  static napi_value PlusOne(napi_env env, napi_callback_info info);-  double counter_;-  napi_env env_;-  napi_ref wrapper_;-};--#endif  // TEST_ADDONS_NAPI_7_FACTORY_WRAP_MYOBJECT_H_

7_factory_wrap/napi/package.json

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "name": "factory_wrap",-  "version": "0.0.0",-  "description": "Node.js Addons Example #7",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0"-  }-}

7_factory_wrap/node-addon-api/addon.cc

deleted file mode 100644@@ -1,14 +0,0 @@-#include <napi.h>-#include "myobject.h"--Napi::Object CreateObject(const Napi::CallbackInfo& info) {-  return MyObject::NewInstance(info.Env(), info[0]);-}--Napi::Object InitAll(Napi::Env env, Napi::Object exports) {-  Napi::Object new_exports =-      Napi::Function::New(env, CreateObject, "CreateObject");-  return MyObject::Init(env, new_exports);-}--NODE_API_MODULE(addon, InitAll)

7_factory_wrap/node-addon-api/addon.js

deleted file mode 100644@@ -1,11 +0,0 @@-var createObject = require('bindings')('addon');--var obj = createObject(10);-console.log( obj.plusOne() ); // 11-console.log( obj.plusOne() ); // 12-console.log( obj.plusOne() ); // 13--var obj2 = createObject(20);-console.log( obj2.plusOne() ); // 21-console.log( obj2.plusOne() ); // 22-console.log( obj2.plusOne() ); // 23

7_factory_wrap/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "addon.cc", "myobject.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      "defines": [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

7_factory_wrap/node-addon-api/myobject.cc

deleted file mode 100644@@ -1,35 +0,0 @@-#include "myobject.h"-#include <napi.h>-#include <uv.h>--using namespace Napi;--Napi::Object MyObject::Init(Napi::Env env, Napi::Object exports) {-  Napi::Function func = DefineClass(-      env, "MyObject", {InstanceMethod("plusOne", &MyObject::PlusOne)});--  Napi::FunctionReference* constructor = new Napi::FunctionReference();-  *constructor = Napi::Persistent(func);-  env.SetInstanceData(constructor);--  exports.Set("MyObject", func);-  return exports;-}--MyObject::MyObject(const Napi::CallbackInfo& info)-    : Napi::ObjectWrap<MyObject>(info) {-  this->counter_ = info[0].As<Napi::Number>().DoubleValue();-};--Napi::Object MyObject::NewInstance(Napi::Env env, Napi::Value arg) {-  Napi::EscapableHandleScope scope(env);-  Napi::Object obj = env.GetInstanceData<Napi::FunctionReference>()->New({arg});-  return scope.Escape(napi_value(obj)).ToObject();-}--Napi::Value MyObject::PlusOne(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  this->counter_ = this->counter_ + 1;--  return Napi::Number::New(env, this->counter_);-}

7_factory_wrap/node-addon-api/myobject.h

deleted file mode 100644@@ -1,17 +0,0 @@-#ifndef MYOBJECT_H-#define MYOBJECT_H--#include <napi.h>--class MyObject : public Napi::ObjectWrap<MyObject> {- public:-  static Napi::Object Init(Napi::Env env, Napi::Object exports);-  static Napi::Object NewInstance(Napi::Env env, Napi::Value arg);-  MyObject(const Napi::CallbackInfo& info);-- private:-  Napi::Value PlusOne(const Napi::CallbackInfo& info);-  double counter_;-};--#endif

7_factory_wrap/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "factory_wrap",-  "version": "0.0.0",-  "description": "Node.js Addons Example #7",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "engines": {-    "node": "~10 >=10.20 || >=12.17"-  },-  "dependencies": {-    "bindings": "~1.2.1",-    "node-addon-api": "^7.0.0"-  }-}

8_passing_wrapped/nan/addon.cc

deleted file mode 100644@@ -1,40 +0,0 @@-#include <nan.h>-#include "myobject.h"--using namespace v8;--void CreateObject(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  info.GetReturnValue().Set(MyObject::NewInstance(info[0]));-}--void Add(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();--  MyObject* obj1 = Nan::ObjectWrap::Unwrap<MyObject>(-      info[0]->ToObject(context).ToLocalChecked());-  MyObject* obj2 = Nan::ObjectWrap::Unwrap<MyObject>(-      info[1]->ToObject(context).ToLocalChecked());-  double sum = obj1->Val() + obj2->Val();-  info.GetReturnValue().Set(Nan::New(sum));-}--void InitAll(v8::Local<v8::Object> exports) {-  v8::Local<v8::Context> context =-      exports->GetCreationContext().ToLocalChecked();--  MyObject::Init();--  exports->Set(context,-               Nan::New("createObject").ToLocalChecked(),-               Nan::New<v8::FunctionTemplate>(CreateObject)-                   ->GetFunction(context)-                   .ToLocalChecked());--  exports->Set(context,-               Nan::New("add").ToLocalChecked(),-               Nan::New<v8::FunctionTemplate>(Add)-                   ->GetFunction(context)-                   .ToLocalChecked());-}--NODE_MODULE(addon, InitAll)

8_passing_wrapped/nan/addon.js

deleted file mode 100644@@ -1,7 +0,0 @@-var addon = require('bindings')('addon');--var obj1 = addon.createObject(10);-var obj2 = addon.createObject(20);-var result = addon.add(obj1, obj2);--console.log(result); // 30

8_passing_wrapped/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc", "myobject.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

8_passing_wrapped/nan/myobject.cc

deleted file mode 100644@@ -1,43 +0,0 @@-#include "myobject.h"-#include <node.h>--MyObject::MyObject(){};-MyObject::~MyObject(){};--Nan::Persistent<v8::Function> MyObject::constructor;--void MyObject::Init() {-  Nan::HandleScope scope;--  // Prepare constructor template-  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);-  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());-  tpl->InstanceTemplate()->SetInternalFieldCount(1);--  constructor.Reset(-      tpl->GetFunction(Nan::GetCurrentContext()).ToLocalChecked());-}--void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {-  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();-  MyObject* obj = new MyObject();-  obj->val_ =-      info[0]->IsUndefined() ? 0 : info[0]->NumberValue(context).FromJust();-  obj->Wrap(info.This());--  info.GetReturnValue().Set(info.This());-}--v8::Local<v8::Object> MyObject::NewInstance(v8::Local<v8::Value> arg) {-  Nan::EscapableHandleScope scope;--  const unsigned argc = 1;-  v8::Local<v8::Value> argv[argc] = {arg};-  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);-  v8::Local<v8::Context> context =-      v8::Isolate::GetCurrent()->GetCurrentContext();-  v8::Local<v8::Object> instance =-      cons->NewInstance(context, argc, argv).ToLocalChecked();--  return scope.Escape(instance);-}

8_passing_wrapped/nan/myobject.h

deleted file mode 100644@@ -1,21 +0,0 @@-#ifndef MYOBJECT_H-#define MYOBJECT_H--#include <nan.h>--class MyObject : public Nan::ObjectWrap {- public:-  static void Init();-  static v8::Local<v8::Object> NewInstance(v8::Local<v8::Value> arg);-  double Val() const { return val_; }-- private:-  MyObject();-  ~MyObject();--  static Nan::Persistent<v8::Function> constructor;-  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);-  double val_;-};--#endif

8_passing_wrapped/nan/package.json

deleted file mode 100644@@ -1,12 +0,0 @@-{-  "name": "passing_wrapped",-  "version": "0.0.0",-  "description": "Node.js Addons Example #8",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0",-    "nan": "^2.0.0"-  }-}

8_passing_wrapped/napi/addon.cc

deleted file mode 100644@@ -1,59 +0,0 @@-#include <assert.h>-#include "myobject.h"--napi_value CreateObject(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value args[1];-  status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);-  assert(status == napi_ok);--  napi_value instance;-  status = MyObject::NewInstance(env, args[0], &instance);--  return instance;-}--napi_value Add(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 2;-  napi_value args[2];-  status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);-  assert(status == napi_ok);--  MyObject* obj1;-  status = napi_unwrap(env, args[0], reinterpret_cast<void**>(&obj1));-  assert(status == napi_ok);--  MyObject* obj2;-  status = napi_unwrap(env, args[1], reinterpret_cast<void**>(&obj2));-  assert(status == napi_ok);--  napi_value sum;-  status = napi_create_double(env, obj1->Val() + obj2->Val(), &sum);-  assert(status == napi_ok);--  return sum;-}--#define DECLARE_NAPI_METHOD(name, func)                                        \-  { name, 0, func, 0, 0, 0, napi_default, 0 }--napi_value Init(napi_env env, napi_value exports) {-  napi_status status;--  MyObject::Init(env);--  napi_property_descriptor desc[] = {-      DECLARE_NAPI_METHOD("createObject", CreateObject),-      DECLARE_NAPI_METHOD("add", Add),-  };-  status =-      napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc);-  assert(status == napi_ok);-  return exports;-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

8_passing_wrapped/napi/addon.js

deleted file mode 100644@@ -1,7 +0,0 @@-var addon = require('bindings')('addon');--var obj1 = addon.createObject(10);-var obj2 = addon.createObject(20);-var result = addon.add(obj1, obj2);--console.log(result); // 30

8_passing_wrapped/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [ "addon.cc", "myobject.cc" ]-    }-  ]-}

8_passing_wrapped/napi/myobject.cc

deleted file mode 100644@@ -1,111 +0,0 @@-#include "myobject.h"-#include <assert.h>--MyObject::MyObject() : env_(nullptr), wrapper_(nullptr) {}--MyObject::~MyObject() {-  napi_delete_reference(env_, wrapper_);-}--void MyObject::Destructor(napi_env env,-                          void* nativeObject,-                          void* /*finalize_hint*/) {-  reinterpret_cast<MyObject*>(nativeObject)->~MyObject();-}--napi_status MyObject::Init(napi_env env) {-  napi_status status;--  napi_value cons;-  status = napi_define_class(-      env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 0, nullptr, &cons);-  if (status != napi_ok) return status;--  // We will need the constructor `cons` later during the life cycle of the-  // application, so we store a persistent reference to it as the instance data-  // for our addon. This will enable us to use `napi_get_instance_data` at any-  // point during the life cycle of our addon to retrieve it. We cannot simply-  // store it as a global static variable, because that will render our addon-  // unable to support Node.js worker threads and multiple contexts on a single-  // thread.-  //-  // The finalizer we pass as a lambda will be called when our addon is unloaded-  // and is responsible for releasing the persistent reference and freeing the-  // heap memory where we stored the persistent reference.-  napi_ref* constructor = new napi_ref;-  status = napi_create_reference(env, cons, 1, constructor);-  assert(status == napi_ok);-  status = napi_set_instance_data(-      env,-      constructor,-      [](napi_env env, void* data, void* hint) {-        napi_ref* constructor = static_cast<napi_ref*>(data);-        napi_status status = napi_delete_reference(env, *constructor);-        assert(status == napi_ok);-        delete constructor;-      },-      nullptr);-  assert(status == napi_ok);--  return napi_ok;-}--napi_value MyObject::New(napi_env env, napi_callback_info info) {-  napi_status status;--  size_t argc = 1;-  napi_value args[1];-  napi_value jsthis;-  status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);-  assert(status == napi_ok);--  MyObject* obj = new MyObject();--  napi_valuetype valuetype;-  status = napi_typeof(env, args[0], &valuetype);-  assert(status == napi_ok);--  if (valuetype == napi_undefined) {-    obj->val_ = 0;-  } else {-    status = napi_get_value_double(env, args[0], &obj->val_);-    assert(status == napi_ok);-  }--  obj->env_ = env;-  status = napi_wrap(env,-                     jsthis,-                     reinterpret_cast<void*>(obj),-                     MyObject::Destructor,-                     nullptr,  // finalize_hint-                     &obj->wrapper_);-  assert(status == napi_ok);--  return jsthis;-}--napi_value MyObject::Constructor(napi_env env) {-  void* instance_data = nullptr;-  napi_status status = napi_get_instance_data(env, &instance_data);-  assert(status == napi_ok);-  napi_ref* constructor = static_cast<napi_ref*>(instance_data);--  napi_value cons;-  status = napi_get_reference_value(env, *constructor, &cons);-  assert(status == napi_ok);-  return cons;-}--napi_status MyObject::NewInstance(napi_env env,-                                  napi_value arg,-                                  napi_value* instance) {-  napi_status status;--  const int argc = 1;-  napi_value argv[argc] = {arg};--  status = napi_new_instance(env, Constructor(env), argc, argv, instance);-  if (status != napi_ok) return status;--  return napi_ok;-}

8_passing_wrapped/napi/myobject.h

deleted file mode 100644@@ -1,26 +0,0 @@-#ifndef TEST_ADDONS_NAPI_8_PASSING_WRAPPED_MYOBJECT_H_-#define TEST_ADDONS_NAPI_8_PASSING_WRAPPED_MYOBJECT_H_--#include <node_api.h>--class MyObject {- public:-  static napi_status Init(napi_env env);-  static void Destructor(napi_env env, void* nativeObject, void* finalize_hint);-  static napi_status NewInstance(napi_env env,-                                 napi_value arg,-                                 napi_value* instance);-  double Val() const { return val_; }-- private:-  MyObject();-  ~MyObject();--  static inline napi_value Constructor(napi_env env);-  static napi_value New(napi_env env, napi_callback_info info);-  double val_;-  napi_env env_;-  napi_ref wrapper_;-};--#endif  // TEST_ADDONS_NAPI_8_PASSING_WRAPPED_MYOBJECT_H_

8_passing_wrapped/napi/package.json

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "name": "passing_wrapped",-  "version": "0.0.0",-  "description": "Node.js Addons Example #8",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.5.0"-  }-}

8_passing_wrapped/node-addon-api/addon.cc

deleted file mode 100644@@ -1,31 +0,0 @@-#include <napi.h>-#include "myobject.h"--using namespace Napi;--Napi::Object CreateObject(const Napi::CallbackInfo& info) {-  return MyObject::NewInstance(info.Env(), info[0]);-}--Napi::Number Add(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  MyObject* obj1 =-      Napi::ObjectWrap<MyObject>::Unwrap(info[0].As<Napi::Object>());-  MyObject* obj2 =-      Napi::ObjectWrap<MyObject>::Unwrap(info[1].As<Napi::Object>());-  double sum = obj1->Val() + obj2->Val();-  return Napi::Number::New(env, sum);-}--Napi::Object InitAll(Napi::Env env, Napi::Object exports) {-  MyObject::Init(env, exports);--  exports.Set(Napi::String::New(env, "createObject"),-              Napi::Function::New(env, CreateObject));--  exports.Set(Napi::String::New(env, "add"), Napi::Function::New(env, Add));--  return exports;-}--NODE_API_MODULE(addon, InitAll)

8_passing_wrapped/node-addon-api/addon.js

deleted file mode 100644@@ -1,7 +0,0 @@-var addon = require('bindings')('addon');--var obj1 = addon.createObject(10);-var obj2 = addon.createObject(20);-var result = addon.add(obj1, obj2);--console.log(result); // 30

8_passing_wrapped/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,16 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "addon.cc", "myobject.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

8_passing_wrapped/node-addon-api/myobject.cc

deleted file mode 100644@@ -1,24 +0,0 @@-#include "myobject.h"-#include <napi.h>-#include <uv.h>--MyObject::MyObject(const Napi::CallbackInfo& info)-    : Napi::ObjectWrap<MyObject>(info) {-  this->val_ = info[0].As<Napi::Number>().DoubleValue();-};--void MyObject::Init(Napi::Env env, Napi::Object exports) {-  Napi::Function func = DefineClass(env, "MyObject", {});--  Napi::FunctionReference* constructor = new Napi::FunctionReference();-  *constructor = Napi::Persistent(func);-  env.SetInstanceData(constructor); //NOTE: this assumes only 1 class is exported-                                    //for multiple exported classes, need a struct or other mechanism--  exports.Set("MyObject", func);-}--Napi::Object MyObject::NewInstance(Napi::Env env, Napi::Value arg) {-  Napi::Object obj = env.GetInstanceData<Napi::FunctionReference>()->New({arg});-  return obj;-}

8_passing_wrapped/node-addon-api/myobject.h

deleted file mode 100644@@ -1,17 +0,0 @@-#ifndef MYOBJECT_H-#define MYOBJECT_H--#include <napi.h>--class MyObject : public Napi::ObjectWrap<MyObject> {- public:-  static void Init(Napi::Env env, Napi::Object exports);-  static Napi::Object NewInstance(Napi::Env env, Napi::Value arg);-  double Val() const { return val_; }-  MyObject(const Napi::CallbackInfo& info);-- private:-  double val_;-};--#endif

8_passing_wrapped/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "passing_wrapped",-  "version": "0.0.0",-  "description": "Node.js Addons Example #8",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "engines": {-    "node": "~10 >=10.20 || >=12.17"-  },-  "dependencies": {-    "bindings": "~1.5.0",-    "node-addon-api": "^3.0.0"-  }-}

README.md

@@ -15,37 +15,45 @@ Implementations against unsupported versions of Node.js are provided for completeness and historical context. They are not maintained.  The examples are primarily maintained for Node-API and node-addon-api and as outlined in-the Node.js [documentation](https://nodejs.org/dist/latest/docs/api/addons.html), +the Node.js [documentation](https://nodejs.org/dist/latest/docs/api/addons.html), unless there is a need for direct access to functionality which-is not exposed by Node-API, use Node-API. +is not exposed by Node-API, use Node-API. -The [Node-API Resource](http://nodejs.github.io/node-addon-examples/) offers an -excellent orientation and tips for developers just getting started with Node-API +The [Node-API Resource](http://nodejs.github.io/node-addon-examples/) offers an+excellent orientation and tips for developers just getting started with Node-API and `node-addon-api`.  ## Usage  The directory structure is as follows: +```sh+REPO_ROOT+├── test_all.js+├── package.json+├── README.md+└── src+    ├── 1-getting-started+    │   ├── example1+    │   │   ├── nan+    │   │   ├── node-addon-api+    │   │   └── napi+    │   ├── example2+    │   └── example3+    ├── 2-js-to-native-conversion+    ├── 3-context-awareness+    ├── 4-references-and-handle-scope+    ├── 5-async-work+    ├── 6-threadsafe-function+    ├── 7-events+    └── 8-tooling ```-<name of example>-  |-  +--- <implementation 1>-  |      |-  |      +--- files...-  +--- <implementation 2>-  .      |-  .      +--- files...-  .-```-  In each example's implementation subdirectory, run  ```text-$ npm install-$ node ./+npm install+node ./ ```  to see the example in action.-

a-first-project/node-addon-api/README.md

deleted file mode 100644@@ -1,14 +0,0 @@-# Node-API A First Project--This is an example project that accompanies the Node-API workshop tutorials--A tutorial describing this project can be found at the [Node-API Resource](https://napi.inspiredware.com/getting-started/first.html).--To build and run this program on your system, clone it to your computer and run these two commands inside your clone:--```-npm install-npm test-```--> You need to have Node 10.5.0 or later installed. \ No newline at end of file

a-first-project/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,20 +0,0 @@-{-  'targets': [-    {-      'target_name': 'hello-world-native',-      'sources': [ 'src/hello_world.cc' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'xcode_settings': {-        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-        'CLANG_CXX_LIBRARY': 'libc++',-        'MACOSX_DEPLOYMENT_TARGET': '10.7'-      },-      'msvs_settings': {-        'VCCLCompilerTool': { 'ExceptionHandling': 1 },-      }-    }-  ]-}\ No newline at end of file

a-first-project/node-addon-api/lib/binding.js

deleted file mode 100644@@ -1,4 +0,0 @@-const addon = require('../build/Release/hello-world-native');--module.exports = addon.HelloWorld-

a-first-project/node-addon-api/package.json

deleted file mode 100644@@ -1,16 +0,0 @@-{-  "main": "lib/binding.js",-  "private": true,-  "dependencies": {-    "node-addon-api": "^1.1.0"-  },-  "scripts": {-    "test": "node --napi-modules ./test/test_binding.js"-  },-  "gypfile": true,-  "name": "hello-world",-  "version": "1.0.0",-  "description": "A first project.",-  "author": "Your name goes here",-  "license": "ISC"-}

a-first-project/node-addon-api/src/hello_world.cc

deleted file mode 100644@@ -1,16 +0,0 @@-#include <napi.h>--using namespace Napi;--Napi::String Method(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  return Napi::String::New(env, "world");-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "HelloWorld"),-              Napi::Function::New(env, Method));-  return exports;-}--NODE_API_MODULE(addon, Init)

a-first-project/node-addon-api/test/test_binding.js

deleted file mode 100644@@ -1,14 +0,0 @@-const HelloWorld = require("../lib/binding.js");-const assert = require("assert");--assert(HelloWorld, "The expected function is undefined");--function testBasic()-{-    const result =  HelloWorld("hello");-    assert.strictEqual(result, "world", "Unexpected value returned");-}--assert.doesNotThrow(testBasic, undefined, "testBasic threw an expection");--console.log("Tests passed- everything looks OK!");\ No newline at end of file

array_buffer_to_native/node-addon-api/array_buffer_to_native.cc

deleted file mode 100644@@ -1,35 +0,0 @@-#include <napi.h>-#include <stdio.h>--static void ArrayConsumer(const int32_t* array, size_t length) {-  for (size_t index = 0; index < length; index++) {-    fprintf(stderr, "array[%lu] = %d\n", index, array[index]);-  }-}--static Napi::Value AcceptArrayBuffer(const Napi::CallbackInfo& info) {-  if (info.Length() != 1) {-    Napi::Error::New(info.Env(), "Expected exactly one argument")-        .ThrowAsJavaScriptException();-    return info.Env().Undefined();-  }-  if (!info[0].IsArrayBuffer()) {-    Napi::Error::New(info.Env(), "Expected an ArrayBuffer")-        .ThrowAsJavaScriptException();-    return info.Env().Undefined();-  }--  Napi::ArrayBuffer buf = info[0].As<Napi::ArrayBuffer>();--  ArrayConsumer(reinterpret_cast<int32_t*>(buf.Data()),-                buf.ByteLength() / sizeof(int32_t));--  return info.Env().Undefined();-}--static Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports["AcceptArrayBuffer"] = Napi::Function::New(env, AcceptArrayBuffer);-  return exports;-}--NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

array_buffer_to_native/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "array_buffer_to_native",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "array_buffer_to_native.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

array_buffer_to_native/node-addon-api/index.js

deleted file mode 100644@@ -1,15 +0,0 @@-const binding = require('bindings')('array_buffer_to_native');-const array = new Int32Array(10);--array[0] = 19;-array[1] = -41;-array[2] = 98;-array[3] = -922;-array[4] = 587;-array[5] = 12;-array[6] = 221;-array[7] = 49;-array[8] = -96;-array[9] = -1;--binding.AcceptArrayBuffer(array.buffer);

array_buffer_to_native/node-addon-api/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "array_buffer_to_native",-  "version": "0.0.0",-  "description": "Fill Out a Native Array in JavaScript",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "node-addon-api": "^1.0.0"-  },-  "scripts": {-    "test": "node index.js"-  }-}

async-iterator/node-addon-api/CMakeLists.txt

deleted file mode 100644@@ -1,23 +0,0 @@-project (example)-include_directories(${CMAKE_JS_INC} node_modules/node-addon-api/)-cmake_minimum_required(VERSION 3.18)--set(CMAKE_CXX_STANDARD 20)-set(CMAKE_CXX_STANDARD_REQUIRED ON)-include_directories(${CMAKE_JS_INC})-file(GLOB SOURCE_FILES "*.cc")-add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")-target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})--# Include Node-API wrappers-execute_process(COMMAND node -p "require('node-addon-api').include"-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}-        OUTPUT_VARIABLE NODE_ADDON_API_DIR-        )-string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})--target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})--# define NAPI_VERSION-add_definitions(-DNAPI_VERSION=6)

async-iterator/node-addon-api/example.cc

deleted file mode 100644@@ -1,84 +0,0 @@-#include <napi.h>-#include <memory>--using namespace Napi;--class AsyncIteratorExample : public ObjectWrap<AsyncIteratorExample> {- public:-  AsyncIteratorExample(const CallbackInfo& info)-      : ObjectWrap<AsyncIteratorExample>(info),-        _from(info[0].As<Number>()),-        _to(info[1].As<Number>()) {}--  static Object Init(Napi::Env env, Napi::Object exports) {-    Napi::Function func = DefineClass(-        env,-        "AsyncIteratorExample",-        {InstanceMethod(Napi::Symbol::WellKnown(env, "asyncIterator"),-                        &AsyncIteratorExample::Iterator)});--    exports.Set("AsyncIteratorExample", func);-    return exports;-  }--  Napi::Value Iterator(const CallbackInfo& info) {-    auto env = info.Env();-    auto iteratorObject = Napi::Object::New(env);--    iteratorObject["current"] = Number::New(env, _from);-    iteratorObject["last"] = Number::New(env, _to);-    auto next = Function::New(env, [](const CallbackInfo& info) {-      auto env = info.Env();-      auto deferred =-          std::make_shared<Promise::Deferred>(Promise::Deferred::New(env));-      auto iteratorObject = info.This().As<Object>();-      auto callback = Function::New(-          env,-          [=](const CallbackInfo& info) {-            auto env = info.Env();-            auto value = Object::New(env);-            auto iteratorObject = info.This().As<Object>();--            auto current =-                iteratorObject.Get("current").As<Number>().Int32Value();-            auto last = iteratorObject.Get("last").As<Number>().Int32Value();-            auto done = current > last;--            if (done) {-              value["done"] = Boolean::New(env, true);-            } else {-              value["done"] = Boolean::New(env, false);-              value["value"] = Number::New(env, current);-              iteratorObject["current"] = Number::New(env, current + 1);-            }-            deferred->Resolve(value);-          },-          "next");--      env.Global()-          .Get("setTimeout")-          .As<Function>()-          .Call({callback.Get("bind").As<Function>().Call(callback,-                                                          {iteratorObject}),-                 Number::New(env, 1000)});--      return deferred->Promise();-    });--    iteratorObject["next"] =-        next.Get("bind").As<Function>().Call(next, {iteratorObject});--    return iteratorObject;-  }-- private:-  int _from;-  int _to;-};--Napi::Object Init(Napi::Env env, Object exports) {-  AsyncIteratorExample::Init(env, exports);-  return exports;-}--NODE_API_MODULE(example, Init)

async-iterator/node-addon-api/index.js

deleted file mode 100644@@ -1,49 +0,0 @@-const { AsyncIteratorExample } = require('bindings')('example');--async function main(from, to) {-    const iterator = new AsyncIteratorExample(from, to);-    for await (const value of iterator) {-        console.log(value);-    }-}--/*-// The JavaScript equivalent of the node-addon-api C++ code for reference-async function main(from, to) {-    class AsyncIteratorExample {-        constructor(from, to) {-            this.from = from;-            this.to = to;-        }--        [Symbol.asyncIterator]() {-            return {-                current: this.from,-                last: this.to,-                next() {-                    return new Promise(resolve => {-                        setTimeout(() => {-                            if (this.current <= this.last) {-                                resolve({ done: false, value: this.current++ });-                            } else {-                                resolve({ done: true });-                            }-                        }, 1000)-                    });-                }-            }-        }-    }-    const iterator = new AsyncIteratorExample(from, to);--    for await (const value of iterator) {-        console.log(value);-    }-}-*/--main(0, 5)-    .catch(e => {-        console.error(e);-        process.exit(1);-    });

async-iterator/node-addon-api/package.json

deleted file mode 100644@@ -1,16 +0,0 @@-{-  "name": "async-iterator-example",-  "version": "0.0.0",-  "description": "Async iterator example using node-addon-api",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "^1.5.0",-    "cmake-js": "^6.3.0",-    "node-addon-api": "^5.0.0"-  },-  "scripts": {-    "test": "node index.js",-    "install": "cmake-js compile"-  }-}

async_pi_estimate/nan/README.md

deleted file mode 100755@@ -1 +0,0 @@-In this directory run `node-gyp rebuild` and then `node ./addon.js`\ No newline at end of file

async_pi_estimate/nan/addon.cc

deleted file mode 100755@@ -1,24 +0,0 @@-#include <nan.h>-#include "async.h"  // NOLINT(build/include)-#include "sync.h"   // NOLINT(build/include)--using Nan::GetFunction;-using Nan::New;-using Nan::Set;-using v8::FunctionTemplate;-using v8::Object;-using v8::String;--// Expose synchronous and asynchronous access to our-// Estimate() function-NAN_MODULE_INIT(InitAll) {-  Set(target,-      New<String>("calculateSync").ToLocalChecked(),-      GetFunction(New<FunctionTemplate>(CalculateSync)).ToLocalChecked());--  Set(target,-      New<String>("calculateAsync").ToLocalChecked(),-      GetFunction(New<FunctionTemplate>(CalculateAsync)).ToLocalChecked());-}--NODE_MODULE(addon, InitAll)

async_pi_estimate/nan/addon.js

deleted file mode 100755@@ -1,44 +0,0 @@-var addon = require('./build/Release/addon');-var calculations = process.argv[2] || 100000000;--function printResult(type, pi, ms) {-  console.log(type, 'method:');-  console.log('\tπ ≈ ' + pi +-              ' (' + Math.abs(pi - Math.PI) + ' away from actual)');-  console.log('\tTook ' + ms + 'ms');-  console.log();-}--function runSync() {-  var start = Date.now();-  // Estimate() will execute in the current thread,-  // the next line won't return until it is finished-  var result = addon.calculateSync(calculations);-  printResult('Sync', result, Date.now() - start);-}--function runAsync() {-  // how many batches should we split the work in to?-  var batches = process.argv[3] || 16;-  var ended = 0;-  var total = 0;-  var start = Date.now();--  function done (err, result) {-    total += result;--    // have all the batches finished executing?-    if (++ended === batches) {-      printResult('Async', total / batches, Date.now() - start);-    }-  }--  // for each batch of work, request an async Estimate() for-  // a portion of the total number of calculations-  for (var i = 0; i < batches; i++) {-    addon.calculateAsync(calculations / batches, done);-  }-}--runSync();-runAsync();

async_pi_estimate/nan/async.cc

deleted file mode 100755@@ -1,51 +0,0 @@-#include "async.h"  // NOLINT(build/include)-#include <nan.h>-#include "pi_est.h"  // NOLINT(build/include)--using Nan::AsyncQueueWorker;-using Nan::AsyncWorker;-using Nan::Callback;-using Nan::HandleScope;-using Nan::New;-using Nan::Null;-using Nan::To;-using v8::Function;-using v8::Local;-using v8::Number;-using v8::Value;--class PiWorker : public AsyncWorker {- public:-  PiWorker(Callback* callback, int points)-      : AsyncWorker(callback), points(points), estimate(0) {}-  ~PiWorker() {}--  // Executed inside the worker-thread.-  // It is not safe to access V8, or V8 data structures-  // here, so everything we need for input and output-  // should go on `this`.-  void Execute() { estimate = Estimate(points); }--  // Executed when the async work is complete-  // this function will be run inside the main event loop-  // so it is safe to use V8 again-  void HandleOKCallback() {-    HandleScope scope;--    Local<Value> argv[] = {Null(), New<Number>(estimate)};--    callback->Call(2, argv, async_resource);-  }-- private:-  int points;-  double estimate;-};--// Asynchronous access to the `Estimate()` function-NAN_METHOD(CalculateAsync) {-  int points = To<int>(info[0]).FromJust();-  Callback* callback = new Callback(To<Function>(info[1]).ToLocalChecked());--  AsyncQueueWorker(new PiWorker(callback, points));-}

async_pi_estimate/nan/async.h

deleted file mode 100755@@ -1,8 +0,0 @@-#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_-#define EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_--#include <nan.h>--NAN_METHOD(CalculateAsync);--#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_

async_pi_estimate/nan/binding.gyp

deleted file mode 100755@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [-        "addon.cc",-        "pi_est.cc",-        "sync.cc",-        "async.cc"-      ],-      "include_dirs": ["<!(node -e \"require('nan')\")"]-    }-  ]-}

async_pi_estimate/nan/package.json

deleted file mode 100755@@ -1,14 +0,0 @@-{-  "name": "async_work",-  "version": "0.0.0",-  "description": "Node.js Addons Example #9",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "scripts": {-    "test": "node addon.js"-  },-  "dependencies": {-    "nan": "*"-  }-}

async_pi_estimate/nan/pi_est.cc

deleted file mode 100755@@ -1,54 +0,0 @@-#include "pi_est.h"  // NOLINT(build/include)-#include <cstdlib>--/*-Estimate the value of π by using a Monte Carlo method.-Take `points` samples of random x and y values on a-[0,1][0,1] plane. Calculating the length of the diagonal-tells us whether the point lies inside, or outside a-quarter circle running from 0,1 to 1,0. The ratio of the-number of points inside to outside gives us an-approximation of π/4.--See https://en.wikipedia.org/wiki/File:Pi_30K.gif-for a visualization of how this works.-*/--inline int randall(unsigned int* p_seed) {-// windows has thread safe rand()-#ifdef _WIN32-  return rand();  // NOLINT(runtime/threadsafe_fn)-#else-  return rand_r(p_seed);-#endif-}--double Estimate(int points) {-  int i = points;-  int inside = 0;-  unsigned int randseed = 1;--#ifdef _WIN32-  srand(randseed);-#endif--  // unique seed for each run, for threaded use-  unsigned int seed = randall(&randseed);--#ifdef _WIN32-  srand(seed);-#endif--  while (i-- > 0) {-    double x = randall(&seed) / static_cast<double>(RAND_MAX);-    double y = randall(&seed) / static_cast<double>(RAND_MAX);--    // x & y and now values between 0 and 1-    // now do a pythagorean diagonal calculation-    // `1` represents our 1/4 circle-    if ((x * x) + (y * y) <= 1) inside++;-  }--  // calculate ratio and multiply by 4 for π-  return (inside / static_cast<double>(points)) * 4;-}

async_pi_estimate/nan/pi_est.h

deleted file mode 100755@@ -1,6 +0,0 @@-#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_-#define EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_--double Estimate(int points);--#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_

async_pi_estimate/nan/sync.cc

deleted file mode 100755@@ -1,12 +0,0 @@-#include "sync.h"  // NOLINT(build/include)-#include <nan.h>-#include "pi_est.h"  // NOLINT(build/include)--// Simple synchronous access to the `Estimate()` function-NAN_METHOD(CalculateSync) {-  // expect a number as the first argument-  int points = info[0]->Uint32Value(Nan::GetCurrentContext()).FromJust();-  double est = Estimate(points);--  info.GetReturnValue().Set(est);-}

async_pi_estimate/nan/sync.h

deleted file mode 100755@@ -1,8 +0,0 @@-#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_-#define EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_--#include <nan.h>--NAN_METHOD(CalculateSync);--#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_

async_pi_estimate/node-addon-api/README.md

deleted file mode 100755@@ -1 +0,0 @@-In this directory run `node-gyp rebuild` and then `node ./addon.js`\ No newline at end of file

async_pi_estimate/node-addon-api/addon.cc

deleted file mode 100755@@ -1,15 +0,0 @@-#include <napi.h>-#include "async.h"  // NOLINT(build/include)-#include "sync.h"   // NOLINT(build/include)--// Expose synchronous and asynchronous access to our-// Estimate() function-Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "calculateSync"),-              Napi::Function::New(env, CalculateSync));-  exports.Set(Napi::String::New(env, "calculateAsync"),-              Napi::Function::New(env, CalculateAsync));-  return exports;-}--NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

async_pi_estimate/node-addon-api/addon.js

deleted file mode 100755@@ -1,44 +0,0 @@-var addon = require('bindings')('addon');-var calculations = process.argv[2] || 100000000;--function printResult(type, pi, ms) {-  console.log(type, 'method:');-  console.log('\tπ ≈ ' + pi +-              ' (' + Math.abs(pi - Math.PI) + ' away from actual)');-  console.log('\tTook ' + ms + 'ms');-  console.log();-}--function runSync() {-  var start = Date.now();-  // Estimate() will execute in the current thread,-  // the next line won't return until it is finished-  var result = addon.calculateSync(calculations);-  printResult('Sync', result, Date.now() - start);-}--function runAsync() {-  // how many batches should we split the work in to?-  var batches = process.argv[3] || 16;-  var ended = 0;-  var total = 0;-  var start = Date.now();--  function done (err, result) {-    total += result;--    // have all the batches finished executing?-    if (++ended === batches) {-      printResult('Async', total / batches, Date.now() - start);-    }-  }--  // for each batch of work, request an async Estimate() for-  // a portion of the total number of calculations-  for (var i = 0; i < batches; i++) {-    addon.calculateAsync(calculations / batches, done);-  }-}--runSync();-runAsync();

async_pi_estimate/node-addon-api/async.cc

deleted file mode 100755@@ -1,36 +0,0 @@-#include "async.h"  // NOLINT(build/include)-#include <napi.h>-#include "pi_est.h"  // NOLINT(build/include)--class PiWorker : public Napi::AsyncWorker {- public:-  PiWorker(Napi::Function& callback, int points)-      : Napi::AsyncWorker(callback), points(points), estimate(0) {}-  ~PiWorker() {}--  // Executed inside the worker-thread.-  // It is not safe to access JS engine data structure-  // here, so everything we need for input and output-  // should go on `this`.-  void Execute() { estimate = Estimate(points); }--  // Executed when the async work is complete-  // this function will be run inside the main event loop-  // so it is safe to use JS engine data again-  void OnOK() {-    Callback().Call({Env().Undefined(), Napi::Number::New(Env(), estimate)});-  }-- private:-  int points;-  double estimate;-};--// Asynchronous access to the `Estimate()` function-Napi::Value CalculateAsync(const Napi::CallbackInfo& info) {-  int points = info[0].As<Napi::Number>().Uint32Value();-  Napi::Function callback = info[1].As<Napi::Function>();-  PiWorker* piWorker = new PiWorker(callback, points);-  piWorker->Queue();-  return info.Env().Undefined();-}

async_pi_estimate/node-addon-api/async.h

deleted file mode 100755@@ -1,8 +0,0 @@-#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_-#define EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_--#include <napi.h>--Napi::Value CalculateAsync(const Napi::CallbackInfo& info);--#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_

async_pi_estimate/node-addon-api/binding.gyp

deleted file mode 100755@@ -1,33 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [-        "addon.cc",-        "pi_est.cc",-        "sync.cc",-        "async.cc"-      ],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'conditions': [-        ['OS=="win"', {-          "msvs_settings": {-            "VCCLCompilerTool": {-              "ExceptionHandling": 1-            }-          }-        }],-        ['OS=="mac"', {-          "xcode_settings": {-            "CLANG_CXX_LIBRARY": "libc++",-            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-            'MACOSX_DEPLOYMENT_TARGET': '10.7'-          }-        }]-      ]-    }-  ]-}

async_pi_estimate/node-addon-api/package.json

deleted file mode 100755@@ -1,15 +0,0 @@-{-  "name": "async_work",-  "version": "0.0.0",-  "description": "Node.js Addons Example #9",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "scripts": {-    "test": "node addon.js"-  },-  "dependencies": {-    "node-addon-api": "*",-    "bindings": "*"-  }-}

async_pi_estimate/node-addon-api/pi_est.cc

deleted file mode 100755@@ -1,54 +0,0 @@-#include "pi_est.h"  // NOLINT(build/include)-#include <cstdlib>--/*-Estimate the value of π by using a Monte Carlo method.-Take `points` samples of random x and y values on a-[0,1][0,1] plane. Calculating the length of the diagonal-tells us whether the point lies inside, or outside a-quarter circle running from 0,1 to 1,0. The ratio of the-number of points inside to outside gives us an-approximation of π/4.--See https://en.wikipedia.org/wiki/File:Pi_30K.gif-for a visualization of how this works.-*/--inline int randall(unsigned int* p_seed) {-// windows has thread safe rand()-#ifdef _WIN32-  return rand();  // NOLINT(runtime/threadsafe_fn)-#else-  return rand_r(p_seed);-#endif-}--double Estimate(int points) {-  int i = points;-  int inside = 0;-  unsigned int randseed = 1;--#ifdef _WIN32-  srand(randseed);-#endif--  // unique seed for each run, for threaded use-  unsigned int seed = randall(&randseed);--#ifdef _WIN32-  srand(seed);-#endif--  while (i-- > 0) {-    double x = randall(&seed) / static_cast<double>(RAND_MAX);-    double y = randall(&seed) / static_cast<double>(RAND_MAX);--    // x & y and now values between 0 and 1-    // now do a pythagorean diagonal calculation-    // `1` represents our 1/4 circle-    if ((x * x) + (y * y) <= 1) inside++;-  }--  // calculate ratio and multiply by 4 for π-  return (inside / static_cast<double>(points)) * 4;-}

async_pi_estimate/node-addon-api/pi_est.h

deleted file mode 100755@@ -1,6 +0,0 @@-#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_-#define EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_--double Estimate(int points);--#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_

async_pi_estimate/node-addon-api/sync.cc

deleted file mode 100755@@ -1,12 +0,0 @@-#include "sync.h"  // NOLINT(build/include)-#include <napi.h>-#include "pi_est.h"  // NOLINT(build/include)--// Simple synchronous access to the `Estimate()` function-Napi::Value CalculateSync(const Napi::CallbackInfo& info) {-  // expect a number as the first argument-  int points = info[0].As<Napi::Number>().Uint32Value();-  double est = Estimate(points);--  return Napi::Number::New(info.Env(), est);-}

async_pi_estimate/node-addon-api/sync.h

deleted file mode 100755@@ -1,8 +0,0 @@-#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_-#define EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_--#include <napi.h>--Napi::Value CalculateSync(const Napi::CallbackInfo& info);--#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_

async_work_promise/napi/binding.c

deleted file mode 100644@@ -1,170 +0,0 @@-#include <stdio.h>-#include <stdlib.h>-#include <node_api.h>--// Limit ourselves to this many primes, starting at 2-#define PRIME_COUNT 10-#define CHECK(expr) \-  { \-    if ((expr) == 0) { \-      fprintf(stderr, "%s:%d: failed assertion `%s'\n", __FILE__, __LINE__, #expr); \-      fflush(stderr); \-      abort(); \-    } \-  }--typedef struct linked_box_s linked_box_t;-struct linked_box_s {-  linked_box_t* prev;-  int the_prime;-};--typedef struct {-  napi_async_work work;-  napi_deferred deferred;-  int data[PRIME_COUNT];-} AddonData;--// This function runs on a worker thread. It has no access to the JavaScript.-static void ExecuteWork(napi_env env, void* data) {-  AddonData* addon_data = (AddonData*)data;-  int idx_inner, idx_outer;-  int prime_count = 0;--  // Find the first 1000 prime numbers using an extremely inefficient algorithm.-  for (idx_outer = 2; prime_count < PRIME_COUNT; idx_outer++) {-    for (idx_inner = 2; idx_inner < idx_outer; idx_inner++) {-      if (idx_outer % idx_inner == 0) {-        break;-      }-    }-    if (idx_inner < idx_outer) {-      continue;-    }--    // Save the prime number to the heap. The JavaScript marshaller (CallJs)-    // will free this item after having sent it to JavaScript.-    addon_data->data[prime_count] = idx_outer;-    ++prime_count;-  }-}--// This function runs on the main thread after `ExecuteWork` exits.-static void WorkComplete(napi_env env, napi_status status, void* data) {-  if (status != napi_ok) {-    return;-  }--  AddonData* addon_data = (AddonData*)data;-  napi_value array;-  CHECK(napi_create_array(env, &array) == napi_ok);--  for (uint32_t idx = 0; idx < PRIME_COUNT; idx++) {-    napi_value js_the_prime;--    // Convert the integer to a napi_value.-    CHECK(napi_create_int32(env, addon_data->data[idx], &js_the_prime) == napi_ok);--    // Store the js value in the array.-    CHECK(napi_set_element(env, array, idx, js_the_prime) == napi_ok);-  }-  CHECK(napi_resolve_deferred(env, addon_data->deferred, array) == napi_ok);--  // Clean up the work item associated with this run.-  CHECK(napi_delete_async_work(env, addon_data->work) == napi_ok);--  // Set both values to NULL so JavaScript can order a new run of the thread.-  addon_data->work = NULL;-  addon_data->deferred = NULL;-}--// Create a deferred promise and an async queue work item.-static napi_value StartWork(napi_env env, napi_callback_info info) {-  napi_value work_name, promise;-  AddonData* addon_data;--  // Retrieve the per-addon data.-  CHECK(napi_get_cb_info(env,-                          info,-                          NULL,-                          NULL,-                          NULL,-                          (void**)(&addon_data)) == napi_ok);--  // Ensure that no work is currently in progress.-  CHECK(addon_data->work == NULL && "Only one work item must exist at a time");--  // Create a string to describe this asynchronous operation.-  CHECK(napi_create_string_utf8(env,-                                 "Node-API Deferred Promise from Async Work Item",-                                 NAPI_AUTO_LENGTH,-                                 &work_name) == napi_ok);--  // Create a deferred promise which we will resolve at the completion of the work.-  CHECK(napi_create_promise(env,-                             &(addon_data->deferred),-                             &promise) == napi_ok);--  // Create an async work item, passing in the addon data, which will give the-  // worker thread access to the above-created deferred promise.-  CHECK(napi_create_async_work(env,-                                NULL,-                                work_name,-                                ExecuteWork,-                                WorkComplete,-                                addon_data,-                                &(addon_data->work)) == napi_ok);--  // Queue the work item for execution.-  CHECK(napi_queue_async_work(env, addon_data->work) == napi_ok);--  // This causes created `promise` to be returned to JavaScript.-  return promise;-}--// Free the per-addon-instance data.-static void addon_getting_unloaded(napi_env env, void* data, void* hint) {-  AddonData* addon_data = (AddonData*)data;-  CHECK(addon_data->work == NULL &&-      "No work item in progress at module unload");-  free(addon_data);-}--// The commented-out return type and the commented out formal function-// parameters below help us keep in mind the signature of the addon-// initialization function. We write the body as though the return value were as-// commented below and as though there were parameters passed in as commented-// below.-/*napi_value*/ NAPI_MODULE_INIT(/*napi_env env, napi_value exports*/) {--  // Define addon-level data associated with this instance of the addon.-  AddonData* addon_data = (AddonData*)malloc(sizeof(*addon_data));-  addon_data->work = NULL;--  // Define the properties that will be set on exports.-  napi_property_descriptor start_work = {-    "startWork",-    NULL,-    StartWork,-    NULL,-    NULL,-    NULL,-    napi_default,-    addon_data-  };--  // Decorate exports with the above-defined properties.-  CHECK(napi_define_properties(env, exports, 1, &start_work) == napi_ok);--  // Associate the addon data with the exports object, to make sure that when-  // the addon gets unloaded our data gets freed.-  CHECK(napi_wrap(env,-                   exports,-                   addon_data,-                   addon_getting_unloaded,-                   NULL,-                   NULL) == napi_ok);--  // Return the decorated exports object.-  return exports;-}

async_work_promise/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  'targets': [-    {-      'target_name': 'binding',-      'sources': [ 'binding.c' ]-    }-  ]-}

async_work_promise/napi/index.js

deleted file mode 100644@@ -1,10 +0,0 @@-// Use the "bindings" package to locate the native bindings.-const binding = require('bindings')('binding');--// Call the function "startWork" which the native bindings library exposes.-// The function returns a promise which will be resolved at the complete of the-// work with an array of worked out primes. This resolution simply prints them out.-binding.startWork()-  .then((thePrimes) => {-    console.log("Received primes from completed work: " + thePrimes)-  });

async_work_promise/napi/package.json

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "name": "async_work_promise",-  "version": "0.0.0",-  "description": "Calling into JS from the thread pool",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.5.0"-  },-  "engines": {-    "node": ">= 10.6.0"-  },-  "scripts": {-    "test": "node index.js"-  },-  "gypfile": true-}

async_work_promise/node-addon-api/addon.cc

deleted file mode 100644@@ -1,32 +0,0 @@-#include "napi.h"-#include "worker.h"--Napi::Value DoHeavyMath(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();--  if (!info[0].IsNumber()) {-    Napi::TypeError::New(env, "num1 must be a number")-        .ThrowAsJavaScriptException();-    return env.Undefined();-  }-  uint32_t num_1 = info[0].As<Napi::Number>().Uint32Value();-  -  if (!info[1].IsNumber()) {-    Napi::TypeError::New(env, "num2 must be a number")-        .ThrowAsJavaScriptException();-    return env.Undefined();-  }-  uint32_t num_2 = info[1].As<Napi::Number>().Uint32Value();-  -  DoHeavyMathWorker* worker = new DoHeavyMathWorker(env, num_1, num_2);-  worker->Queue();-  return worker->GetPromise();-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "doHeavyMath"),-              Napi::Function::New(env, DoHeavyMath));-  return exports;-}--NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

async_work_promise/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,32 +0,0 @@-{-  "targets": [{-    "target_name": "addon",-    "sources": [-      "addon.cc"-    ],-    "include_dirs": [-      "<!@(node -p \"require('node-addon-api').include\")"-    ],-    'defines': [ 'NAPI_CPP_EXCEPTIONS' ],-    'conditions': [-      [ 'OS=="win"', {-        'defines': [ '_HAS_EXCEPTIONS=1' ],-        'msvs_settings': {-          'VCCLCompilerTool': {-            'ExceptionHandling': 1,-          },-        },-      }],-      [ 'OS=="linux"', {-        "cflags": [ "-fexceptions" ],-        "cflags_cc": [ "-fexceptions" ],-      }],-      [ 'OS=="mac"', {-        'xcode_settings': {-          'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-          'CLANG_CXX_LIBRARY': 'libc++',-        }-      }]-    ],-  }]-}

async_work_promise/node-addon-api/index.js

deleted file mode 100644@@ -1,3 +0,0 @@-const bindings = require("bindings")("addon");--bindings.doHeavyMath(2, 1).then(console.log);

async_work_promise/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "async_worker_promise",-  "version": "0.0.0",-  "description": "AsyncWorker example that returns a Promise",-  "main": "index.js",-  "scripts": {-    "test": "node ."-  },-  "author": "Matthew Keil (matthewkeil)",-  "gypfile": true,-  "dependencies": {-    "bindings": "^1.5.0",-    "node-addon-api": "^7.0.0"-  }-}

async_work_promise/node-addon-api/worker.h

deleted file mode 100644@@ -1,43 +0,0 @@-#include "napi.h"--class DoHeavyMathWorker : public Napi::AsyncWorker {- public:-  DoHeavyMathWorker(const Napi::Env& env, uint32_t num_1, uint32_t num_2)-      : Napi::AsyncWorker{env, "DoHeavyMathWorker"},-        m_deferred{env},-        m_num_1{num_1},-        m_num_2{num_2} {}--  /**-   * GetPromise associated with _deferred for return to JS-   */-  Napi::Promise GetPromise() { return m_deferred.Promise(); }-- protected:-  /**-   * Simulate heavy math work-   */-  void Execute() {-    if (m_num_2 == 0) {-      SetError("Cannot divide by zero");-      return;-    }-    m_result = m_num_1 / m_num_2;-  }--  /**-   * Resolve the promise with the result-   */-  void OnOK() { m_deferred.Resolve(Napi::Number::New(Env(), m_result)); }--  /**-   * Reject the promise with errors-   */-  void OnError(const Napi::Error& err) { m_deferred.Reject(err.Value()); }-- private:-  Napi::Promise::Deferred m_deferred;-  uint32_t m_num_1;-  uint32_t m_num_2;-  uint32_t m_result;-};

async_work_thread_safe_function/napi/binding.c

deleted file mode 100644@@ -1,235 +0,0 @@-#include <assert.h>-#include <stdlib.h>-#define NAPI_EXPERIMENTAL-#include <node_api.h>--// Limit ourselves to this many primes, starting at 2-#define PRIME_COUNT 100000-#define REPORT_EVERY 1000--typedef struct {-  napi_async_work work;-  napi_threadsafe_function tsfn;-} AddonData;---// This function is responsible for converting data coming in from the worker-// thread to napi_value items that can be passed into JavaScript, and for-// calling the JavaScript function.-static void CallJs(napi_env env, napi_value js_cb, void* context, void* data) {-  // This parameter is not used.-  (void) context;-  napi_status status;--  // Retrieve the prime from the item created by the worker thread.-  int the_prime = *(int*)data;--  // env and js_cb may both be NULL if Node.js is in its cleanup phase, and-  // items are left over from earlier thread-safe calls from the worker thread.-  // When env is NULL, we simply skip over the call into Javascript and free the-  // items.-  if (env != NULL) {-    napi_value undefined, js_the_prime;--    // Convert the integer to a napi_value.-    status = napi_create_int32(env, the_prime, &js_the_prime);-    assert(status == napi_ok);--    // Retrieve the JavaScript `undefined` value so we can use it as the `this`-    // value of the JavaScript function call.-    status = napi_get_undefined(env, &undefined);-    assert(status == napi_ok);--    // Call the JavaScript function and pass it the prime that the secondary-    // thread found.-    status = napi_call_function(env,-                              undefined,-                              js_cb,-                              1,-                              &js_the_prime,-                              NULL);-    assert(status == napi_ok);-  }--  // Free the item created by the worker thread.-  free(data);-}--// This function runs on a worker thread. It has no access to the JavaScript-// environment except through the thread-safe function.-static void ExecuteWork(napi_env env, void* data) {-  AddonData* addon_data = (AddonData*)data;-  int idx_inner, idx_outer;-  int prime_count = 0;-  napi_status status;--  // We bracket the use of the thread-safe function by this thread by a call to-  // napi_acquire_threadsafe_function() here, and by a call to-  // napi_release_threadsafe_function() immediately prior to thread exit.-  status = napi_acquire_threadsafe_function(addon_data->tsfn);-  assert(status == napi_ok);--  // Find the first 1000 prime numbers using an extremely inefficient algorithm.-  for (idx_outer = 2; prime_count < PRIME_COUNT; idx_outer++) {-    for (idx_inner = 2; idx_inner < idx_outer; idx_inner++) {-      if (idx_outer % idx_inner == 0) {-        break;-      }-    }-    if (idx_inner < idx_outer) {-      continue;-    }--    // We found a prime. If it's the tenth since the last time we sent one to-    // JavaScript, send it to JavaScript.-    if (!(++prime_count % REPORT_EVERY)) {--      // Save the prime number to the heap. The JavaScript marshaller (CallJs)-      // will free this item after having sent it to JavaScript.-      int* the_prime = malloc(sizeof(*the_prime));-      *the_prime = idx_outer;--      // Initiate the call into JavaScript. The call into JavaScript will not-      // have happened when this function returns, but it will be queued.-      status = napi_call_threadsafe_function(addon_data->tsfn,-                                           the_prime,-                                           napi_tsfn_blocking);-      assert(status == napi_ok);-    }-  }--  // Indicate that this thread will make no further use of the thread-safe function.-  status = napi_release_threadsafe_function(addon_data->tsfn,-                                          napi_tsfn_release);-  assert(status == napi_ok);-}--// This function runs on the main thread after `ExecuteWork` exits.-static void WorkComplete(napi_env env, napi_status status, void* data) {-  AddonData* addon_data = (AddonData*)data;--  // Clean up the thread-safe function and the work item associated with this-  // run.-  status = napi_release_threadsafe_function(addon_data->tsfn,-                                            napi_tsfn_release);-  assert(status == napi_ok);-  status = napi_delete_async_work(env, addon_data->work);-  assert(status == napi_ok);--  // Set both values to NULL so JavaScript can order a new run of the thread.-  addon_data->work = NULL;-  addon_data->tsfn = NULL;-}--// Create a thread-safe function and an async queue work item. We pass the-// thread-safe function to the async queue work item so the latter might have a-// chance to call into JavaScript from the worker thread on which the-// ExecuteWork callback runs.-static napi_value StartThread(napi_env env, napi_callback_info info) {-  size_t argc = 1;-  napi_value js_cb, work_name;-  AddonData* addon_data;-  napi_status status;--  // Retrieve the JavaScript callback we should call with items generated by the-  // worker thread, and the per-addon data.-  status = napi_get_cb_info(env,-                          info,-                          &argc,-                          &js_cb,-                          NULL,-                          (void**)(&addon_data));-  assert(status == napi_ok);--  // Ensure that no work is currently in progress.-  assert(addon_data->work == NULL && "Only one work item must exist at a time");--  // Create a string to describe this asynchronous operation.-  status = napi_create_string_utf8(env,-                                 "Node-API Thread-safe Call from Async Work Item",-                                 NAPI_AUTO_LENGTH,-                                 &work_name);-  assert(status == napi_ok);--  // Convert the callback retrieved from JavaScript into a thread-safe function-  // which we can call from a worker thread.-  status = napi_create_threadsafe_function(env,-                                         js_cb,-                                         NULL,-                                         work_name,-                                         0,-                                         1,-                                         NULL,-                                         NULL,-                                         NULL,-                                         CallJs,-                                         &(addon_data->tsfn));-  assert(status == napi_ok);--  // Create an async work item, passing in the addon data, which will give the-  // worker thread access to the above-created thread-safe function.-  status = napi_create_async_work(env,-                                NULL,-                                work_name,-                                ExecuteWork,-                                WorkComplete,-                                addon_data,-                                &(addon_data->work));-  assert(status == napi_ok);--  // Queue the work item for execution.-  status = napi_queue_async_work(env, addon_data->work);-  assert(status == napi_ok);--  // This causes `undefined` to be returned to JavaScript.-  return NULL;-}--// Free the per-addon-instance data.-static void addon_getting_unloaded(napi_env env, void* data, void* hint) {-  AddonData* addon_data = (AddonData*)data;-  assert(addon_data->work == NULL &&-      "No work item in progress at module unload");-  free(addon_data);-}--// The commented-out return type and the commented out formal function-// parameters below help us keep in mind the signature of the addon-// initialization function. We write the body as though the return value were as-// commented below and as though there were parameters passed in as commented-// below.-/*napi_value*/ NAPI_MODULE_INIT(/*napi_env env, napi_value exports*/) {-  napi_status status;-  // Define addon-level data associated with this instance of the addon.-  AddonData* addon_data = (AddonData*)malloc(sizeof(*addon_data));-  addon_data->work = NULL;--  // Define the properties that will be set on exports.-  napi_property_descriptor start_work = {-    "startThread",-    NULL,-    StartThread,-    NULL,-    NULL,-    NULL,-    napi_default,-    addon_data-  };--  // Decorate exports with the above-defined properties.-  status = napi_define_properties(env, exports, 1, &start_work);-  assert(status == napi_ok);--  // Associate the addon data with the exports object, to make sure that when-  // the addon gets unloaded our data gets freed.-  status = napi_wrap(env,-                   exports,-                   addon_data,-                   addon_getting_unloaded,-                   NULL,-                   NULL);-  assert(status == napi_ok);--  // Return the decorated exports object.-  return exports;-}

async_work_thread_safe_function/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  'targets': [-    {-      'target_name': 'binding',-      'sources': [ 'binding.c' ]-    }-  ]-}

async_work_thread_safe_function/napi/index.js

deleted file mode 100644@@ -1,8 +0,0 @@-// Use the "bindings" package to locate the native bindings.-const binding = require('bindings')('binding');--// Call the function "startThread" which the native bindings library exposes.-// The function accepts a callback which it will call from the worker thread and-// into which it will pass prime numbers. This callback simply prints them out.-binding.startThread((thePrime) =>-  console.log("Received prime from secondary thread: " + thePrime));

async_work_thread_safe_function/napi/package.json

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "name": "async_work_thread_safe_function",-  "version": "0.0.0",-  "description": "Calling into JS from the thread pool",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1"-  },-  "engines": {-    "node": ">= 10.6.0"-  },-  "scripts": {-    "test": "node index.js"-  },-  "gypfile": true-}

build_with_cmake/README.md

deleted file mode 100644@@ -1,33 +0,0 @@-## Building Node-API Addons Using CMake.js--### Examples--The objective of these examples is to demonstrate how to build Node-API addons using [CMake.js](https://github.com/cmake-js/cmake-js#readme).--These example projects assume that CMake.js has been installed globally:--```-npm install -g cmake-js-cmake-js --help-```--Then, in each of the `napi` and `node-addon-api` directories, the following commands build and test each addon:--```-npm install-npm test-```--Complete CMake.js documentation can be found on the [CMake.js GitHub repository](https://github.com/cmake-js/cmake-js#readme).--### NAPI_VERSION--When building Node-API addons, it's important to specify to the build system the Node-API version your code is designed to work with. With CMake.js, this information is specified in the `CMakeLists.txt` file:  --```-add_definitions(-DNAPI_VERSION=3)-```--Since Node-API is ABI-stable, your Node-API addon will work, without recompilation, with the Node-API version you specify in `NAPI_VERSION` and all subsequent Node-API versions. --In the absence of a need for features available only in a specific Node-API version, version 3 is a good choice as it is the version of Node-API that was active when Node-API left experimental status. \ No newline at end of file

build_with_cmake/napi/CMakeLists.txt

deleted file mode 100644@@ -1,13 +0,0 @@-cmake_minimum_required(VERSION 3.9)-cmake_policy(SET CMP0042 NEW)-set (CMAKE_CXX_STANDARD 11)--project (build-napi-with-cmake)-include_directories(${CMAKE_JS_INC})-file(GLOB SOURCE_FILES "hello.c")-add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")-target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})--# Define NAPI_VERSION-add_definitions(-DNAPI_VERSION=3)

build_with_cmake/napi/hello.c

deleted file mode 100644@@ -1,23 +0,0 @@-#include <assert.h>-#include <node_api.h>--static napi_value Method(napi_env env, napi_callback_info info) {-  napi_status status;-  napi_value world;-  status = napi_create_string_utf8(env, "Hello, world!", 13, &world);-  assert(status == napi_ok);-  return world;-}--#define DECLARE_NAPI_METHOD(name, func)                                        \-  { name, 0, func, 0, 0, 0, napi_default, 0 }--static napi_value Init(napi_env env, napi_value exports) {-  napi_status status;-  napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);-  status = napi_define_properties(env, exports, 1, &desc);-  assert(status == napi_ok);-  return exports;-}--NAPI_MODULE(hello, Init)

build_with_cmake/napi/hello.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('build-napi-with-cmake');--console.log(addon.hello()); // 'world'

build_with_cmake/napi/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "build-napi-with-cmake",-  "version": "0.0.0",-  "description": "Build Node-API native addon with CMake.",-  "main": "hello.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1"-  },-  "scripts": {-    "install": "cmake-js compile",-    "test": "node hello.js"-  }-}

build_with_cmake/node-addon-api/CMakeLists.txt

deleted file mode 100644@@ -1,22 +0,0 @@-cmake_minimum_required(VERSION 3.9)-cmake_policy(SET CMP0042 NEW)-set (CMAKE_CXX_STANDARD 11)--project (build-node-addon-api-with-cmake)-include_directories(${CMAKE_JS_INC})-file(GLOB SOURCE_FILES "hello.cc")-add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")-target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})--# Include Node-API wrappers-execute_process(COMMAND node -p "require('node-addon-api').include"-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}-        OUTPUT_VARIABLE NODE_ADDON_API_DIR-        )-string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})--target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})--# define NAPI_VERSION-add_definitions(-DNAPI_VERSION=3)

build_with_cmake/node-addon-api/hello.cc

deleted file mode 100644@@ -1,22 +0,0 @@-#include <napi.h>---static Napi::String Method(const Napi::CallbackInfo& info) {-  // Napi::Env is the opaque data structure containing the environment in which the request is being run. -  // We will need this env when we want to create any new objects inside of the node.js environment-  Napi::Env env = info.Env();-  -  // Create a C++ level variable-  std::string helloWorld = "Hello, world!";-  -  // Return a new javascript string that we copy-construct inside of the node.js environment-  return Napi::String::New(env, helloWorld);-}--static Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "hello"),-              Napi::Function::New(env, Method));-  return exports;-}--NODE_API_MODULE(hello, Init)

build_with_cmake/node-addon-api/hello.js

deleted file mode 100644@@ -1,3 +0,0 @@-var addon = require('bindings')('build-node-addon-api-with-cmake');--console.log(addon.hello()); // 'world'

build_with_cmake/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "build-node-addon-api-with-cmake",-  "version": "0.0.0",-  "description": "Build Node-API native addon with CMake and node-addon-api C++ wrapper.",-  "main": "hello.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "node-addon-api": "^1.0.0"-  },-  "scripts": {-    "install": "cmake-js compile",-    "test": "node hello.js"-  }-}

call-js-from-async-worker-execute/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,28 +0,0 @@-{-  "targets": [-    {-      "target_name": "dispatcher",-      "sources": [ "src/binding.cc" ],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'conditions': [-        ['OS=="win"', {-          "msvs_settings": {-            "VCCLCompilerTool": {-              "ExceptionHandling": 1-            }-          }-        }],-        ['OS=="mac"', {-          "xcode_settings": {-            "CLANG_CXX_LIBRARY": "libc++",-            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-            'MACOSX_DEPLOYMENT_TARGET': '10.7'-          }-        }]-      ]-    }-  ]-}

call-js-from-async-worker-execute/node-addon-api/index.js

deleted file mode 100644@@ -1,25 +0,0 @@-'use strict'--const { EventEmitter } = require('node:events');-const { dispatch } = require('bindings')('dispatcher');--class Socket extends EventEmitter {-  constructor () {-    super();-    dispatch(this.emit.bind(this));-  }-}--const socket = new Socket();--socket.on('open', () => {-  console.log('opened');-});--socket.on('message', (message) => {-  console.log(`message: ${message}`);-});--socket.on('close', () => {-  console.log('closed');-});

call-js-from-async-worker-execute/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "call-js-from-async-worker-execute",-  "version": "0.0.0",-  "description": "Node.js Addons - calls JS from AsyncWorker::Execute",-  "main": "index.js",-  "private": true,-  "gypfile": true,-  "scripts": {-    "start": "node index.js"-  },-  "dependencies": {-    "node-addon-api": "*",-    "bindings": "*"-  }-}

call-js-from-async-worker-execute/node-addon-api/src/binding.cc

deleted file mode 100644@@ -1,101 +0,0 @@-#include <napi.h>--#include <chrono>-#include <thread>--class Dispatcher : public Napi::AsyncWorker {- public:-  Dispatcher(Napi::Env env, Napi::Function& callback)-      : Napi::AsyncWorker(env),-        callback_(callback),-        tsfn_{-            Napi::ThreadSafeFunction::New(env, callback, "Dispatcher", 0, 1)} {}--  virtual ~Dispatcher() override { tsfn_.Release(); }--  void Execute() override {-    // Since this method executes on a thread that is different from the main-    // thread, we can't directly call into JavaScript. To trigger a call into-    // JavaScript from this thread, ThreadSafeFunction needs to be used to-    // communicate with the main thread, so that the main thread can invoke the-    // JavaScript function.--    napi_status status =-        tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {-          js_callback.Call({Napi::String::New(env, "open")});-        });-    if (status != napi_ok) {-      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");-      return;-    }--    std::this_thread::sleep_for(std::chrono::seconds(1));-    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {-      js_callback.Call(-          {Napi::String::New(env, "message"), Napi::String::New(env, "data1")});-    });-    if (status != napi_ok) {-      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");-      return;-    }--    std::this_thread::sleep_for(std::chrono::seconds(1));-    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {-      js_callback.Call(-          {Napi::String::New(env, "message"), Napi::String::New(env, "data2")});-    });-    if (status != napi_ok) {-      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");-      return;-    }--    std::this_thread::sleep_for(std::chrono::seconds(1));-    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {-      js_callback.Call(-          {Napi::String::New(env, "message"), Napi::String::New(env, "data3")});-    });-    if (status != napi_ok) {-      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");-      return;-    }--    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {-      js_callback.Call({Napi::String::New(env, "close")});-    });-    if (status != napi_ok) {-      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");-      return;-    }-  }--  void OnError(Napi::Error const& error) override {-    callback_.Call({Napi::String::New(Env(), "error"), error.Value()});-  }-- private:-  Napi::Function callback_;-  Napi::ThreadSafeFunction tsfn_;-};--void Dispatch(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();--  if (info.Length() < 1 || !info[0].IsFunction()) {-    Napi::TypeError::New(-        env, "The first argument needs to be the callback function.")-        .ThrowAsJavaScriptException();-    return;-  }--  Napi::Function callback = info[0].As<Napi::Function>();--  Dispatcher* dispatcher = new Dispatcher(env, callback);-  dispatcher->Queue();-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set("dispatch", Napi::Function::New(env, Dispatch));-  return exports;-}--NODE_API_MODULE(dispatcher, Init)

emit_event_from_cpp/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,30 +0,0 @@-{-  "targets": [-    {-      "target_name": "emit_from_cpp",-      "sources": [-        "src/emit-from-cpp.cc"-      ],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'conditions': [-        ['OS=="win"', {-          "msvs_settings": {-            "VCCLCompilerTool": {-              "ExceptionHandling": 1-            }-          }-        }],-        ['OS=="mac"', {-          "xcode_settings": {-            "CLANG_CXX_LIBRARY": "libc++",-            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-            'MACOSX_DEPLOYMENT_TARGET': '10.7'-          }-        }]-      ]-    }-  ]-}

emit_event_from_cpp/node-addon-api/index.js

deleted file mode 100644@@ -1,19 +0,0 @@-'use strict'--const EventEmitter = require('events').EventEmitter-const addon = require('bindings')('emit_from_cpp')--const emitter = new EventEmitter()--emitter.on('start', () => {-    console.log('### START ...')-})-emitter.on('data', (evt) => {-    console.log(evt);-})--emitter.on('end', () => {-    console.log('### END ###')-})--addon.callEmit(emitter.emit.bind(emitter))

emit_event_from_cpp/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "emit-event-from-cpp-example",-  "version": "0.0.0",-  "description": "Node.js Addons - emit event from C++ to JS",-  "main": "index.js",-  "private": true,-  "gypfile": true,-  "scripts": {-    "start": "node index.js"-  },-  "dependencies": {-    "node-addon-api": "*",-    "bindings": "*"-  }-}

emit_event_from_cpp/node-addon-api/src/emit-from-cpp.cc

deleted file mode 100644@@ -1,27 +0,0 @@-#include <napi.h>--#include <chrono>-#include <iostream>-#include <thread>--Napi::Value CallEmit(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  Napi::Function emit = info[0].As<Napi::Function>();-  emit.Call({Napi::String::New(env, "start")});-  for (int i = 0; i < 3; i++) {-    std::this_thread::sleep_for(std::chrono::seconds(3));-    emit.Call(-        {Napi::String::New(env, "data"), Napi::String::New(env, "data ...")});-  }-  emit.Call({Napi::String::New(env, "end")});-  return Napi::String::New(env, "OK");-}--// Init-Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "callEmit"),-              Napi::Function::New(env, CallEmit));-  return exports;-}--NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);

function-reference-demo/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,31 +0,0 @@-{-  "targets": [-    {-      "target_name": "addon",-      "sources": [-        "src/binding.cc",-        "src/native-addon.cc"-      ],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'conditions': [-        ['OS=="win"', {-          "msvs_settings": {-            "VCCLCompilerTool": {-              "ExceptionHandling": 1-            }-          }-        }],-        ['OS=="mac"', {-          "xcode_settings": {-            "CLANG_CXX_LIBRARY": "libc++",-            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-            'MACOSX_DEPLOYMENT_TARGET': '10.7'-          }-        }]-      ]-    }-  ]-}

function-reference-demo/node-addon-api/index.js

deleted file mode 100644@@ -1,27 +0,0 @@-'use strict'--const { NativeAddon } = require('bindings')('addon')--function JSFnRef() {-    console.log('Hi! I\'m a JS function reference!')-}--function JSFn() {-    console.log('Hi! I\'m a JS function!')-}--const ITERATIONS = 5--const addon = new NativeAddon(JSFnRef, JSFn)--for (let i = 0; i < ITERATIONS; i++) {-    addon.tryCallByStoredReference()-}--try {-    addon.tryCallByStoredFunction()-} catch (err) {-    console.error('This code crashes because JSFn is valid only inside the constructor function.')-    console.error('The lifespan of the JSFn function is limited to the execution of the constructor function.')-    console.error('After that, the function stored in JSFn is ready to be garbage collected and it cannot be used anymore.')-}

function-reference-demo/node-addon-api/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "function-reference-demo",-  "version": "0.0.0",-  "description": "Tutorial example showing the use of function references.",-  "main": "index.js",-  "gypfile": true,-  "scripts": {-    "start": "node index.js"-  },-  "dependencies": {-    "node-addon-api": "*",-    "bindings": "*"-  }-}

function-reference-demo/node-addon-api/src/binding.cc

deleted file mode 100644@@ -1,9 +0,0 @@-#include <napi.h>-#include "native-addon.h"--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  NativeAddon::Init(env, exports);-  return exports;-}--NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)\ No newline at end of file

function-reference-demo/node-addon-api/src/native-addon.cc

deleted file mode 100644@@ -1,36 +0,0 @@-#include "native-addon.h"-#include <iostream>--Napi::FunctionReference NativeAddon::constructor;--Napi::Object NativeAddon::Init(Napi::Env env, Napi::Object exports) {-  Napi::Function func =-      DefineClass(env,-                  "NativeAddon",-                  {InstanceMethod("tryCallByStoredReference",-                                  &NativeAddon::TryCallByStoredReference),-                   InstanceMethod("tryCallByStoredFunction",-                                  &NativeAddon::TryCallByStoredFunction)});--  constructor = Napi::Persistent(func);-  constructor.SuppressDestruct();--  exports.Set("NativeAddon", func);-  return exports;-}--NativeAddon::NativeAddon(const Napi::CallbackInfo& info)-    : Napi::ObjectWrap<NativeAddon>(info) {-  jsFnRef = Napi::Persistent(info[0].As<Napi::Function>());-  jsFn = info[1].As<Napi::Function>();-}--void NativeAddon::TryCallByStoredReference(const Napi::CallbackInfo& info) {-  // Napi::Env env = info.Env();-  jsFnRef.Call({});-}--void NativeAddon::TryCallByStoredFunction(const Napi::CallbackInfo& info) {-  // Napi::Env env = info.Env();-  jsFn.Call({});-}\ No newline at end of file

function-reference-demo/node-addon-api/src/native-addon.h

deleted file mode 100644@@ -1,15 +0,0 @@-#include <napi.h>--class NativeAddon : public Napi::ObjectWrap<NativeAddon> {- public:-  static Napi::Object Init(Napi::Env env, Napi::Object exports);-  NativeAddon(const Napi::CallbackInfo& info);-- private:-  static Napi::FunctionReference constructor;-  Napi::FunctionReference jsFnRef;-  Napi::Function jsFn;--  void TryCallByStoredReference(const Napi::CallbackInfo& info);-  void TryCallByStoredFunction(const Napi::CallbackInfo& info);-};\ No newline at end of file

inherits_from_event_emitter/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,31 +0,0 @@-{-  "targets": [-    {-      "target_name": "native_emitter",-      "sources": [-        "src/binding.cc",-        "src/native-emitter.cc"-      ],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'conditions': [-        ['OS=="win"', {-          "msvs_settings": {-            "VCCLCompilerTool": {-              "ExceptionHandling": 1-            }-          }-        }],-        ['OS=="mac"', {-          "xcode_settings": {-            "CLANG_CXX_LIBRARY": "libc++",-            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-            'MACOSX_DEPLOYMENT_TARGET': '10.7'-          }-        }]-      ]-    }-  ]-}

inherits_from_event_emitter/node-addon-api/index.js

deleted file mode 100644@@ -1,23 +0,0 @@-'use strict'--const EventEmitter = require('events').EventEmitter-const NativeEmitter = require('bindings')('native_emitter').NativeEmitter-const inherits = require('util').inherits--inherits(NativeEmitter, EventEmitter)--const emitter = new NativeEmitter()--emitter.on('start', () => {-    console.log('### START ...')-})--emitter.on('data', (evt) => {-    console.log(evt)-})--emitter.on('end', () => {-    console.log('### END ###')-})--emitter.callAndEmit()

inherits_from_event_emitter/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "inherits-from-event-emitter-example",-  "version": "0.0.0",-  "description": "Node.js Addons - inherits from event emitter",-  "main": "index.js",-  "private": true,-  "gypfile": true,-  "scripts": {-    "start": "node index.js"-  },-  "dependencies": {-    "node-addon-api": "*",-    "bindings": "*"-  }-}

inherits_from_event_emitter/node-addon-api/src/binding.cc

deleted file mode 100644@@ -1,9 +0,0 @@-#include <napi.h>-#include "native-emitter.h"--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  NativeEmitter::Init(env, exports);-  return exports;-}--NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

inherits_from_event_emitter/node-addon-api/src/native-emitter.cc

deleted file mode 100644@@ -1,40 +0,0 @@-#include <chrono>-#include <iostream>-#include <thread>--#include "native-emitter.h"--Napi::FunctionReference NativeEmitter::constructor;--Napi::Object NativeEmitter::Init(Napi::Env env, Napi::Object exports) {-  Napi::Function func =-      DefineClass(env,-                  "NativeEmitter",-                  {InstanceMethod("callAndEmit", &NativeEmitter::CallAndEmit)});--  constructor = Napi::Persistent(func);-  constructor.SuppressDestruct();--  exports.Set("NativeEmitter", func);-  return exports;-}--NativeEmitter::NativeEmitter(const Napi::CallbackInfo& info)-    : Napi::ObjectWrap<NativeEmitter>(info) {-  // NOOP-}--Napi::Value NativeEmitter::CallAndEmit(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  Napi::Function emit =-      info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();-  emit.Call(info.This(), {Napi::String::New(env, "start")});-  for (int i = 0; i < 3; i++) {-    std::this_thread::sleep_for(std::chrono::seconds(1));-    emit.Call(-        info.This(),-        {Napi::String::New(env, "data"), Napi::String::New(env, "data ...")});-  }-  emit.Call(info.This(), {Napi::String::New(env, "end")});-  return Napi::String::New(env, "OK");-}

inherits_from_event_emitter/node-addon-api/src/native-emitter.h

deleted file mode 100644@@ -1,12 +0,0 @@-#include <napi.h>--class NativeEmitter : public Napi::ObjectWrap<NativeEmitter> {- public:-  static Napi::Object Init(Napi::Env env, Napi::Object exports);-  NativeEmitter(const Napi::CallbackInfo& info);-- private:-  static Napi::FunctionReference constructor;--  Napi::Value CallAndEmit(const Napi::CallbackInfo& info);-};

multiple_load/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  'targets': [-    {-      'target_name': 'multiple_load',-      'sources': [ 'multiple_load.c' ]-    }-  ]-}

multiple_load/napi/index.js

deleted file mode 100644@@ -1,40 +0,0 @@-// Example illustrating the case where a native addon is loaded multiple times.-// This entire file is executed twice, concurrently - once on the main thread,-// and once on a thread launched from the main thread.--// We load the worker threads module, which allows us to launch multiple Node.js-// environments, each in its own thread.-const {-  Worker, isMainThread-} = require('worker_threads');--// We load the native addon.-const addon = require('bindings')('multiple_load');--// The iteration count can be tweaked to ensure that the output from the two-// threads is interleaved. Too few iterations and the output of one thread-// follows the output of the other, not really illustrating the concurrency.-const iterations = 1000;--// This function is an idle loop that performs a random walk from 0 by calling-// into the native addon to either increment or decrement the initial value.-function useAddon(addon, prefix, iterations) {-  if (iterations >= 0) {-    if (Math.random() < 0.5) {-      console.log(prefix + ': new value (decremented): ' + addon.decrement());-    } else {-      console.log(prefix + ': new value (incremented): ' + addon.increment());-    }-    setImmediate(() => useAddon(addon, prefix, --iterations));-  }-}--if (isMainThread) {-  // On the main thread, we launch a worker and wait for it to come online. Then-  // we start the loop.-  (new Worker(__filename)).on('online',-      () => useAddon(addon, "Main thread", iterations));-} else {-  // On the secondary thread we immediately start the loop.-  useAddon(addon, "Worker thread", iterations);-}

multiple_load/napi/multiple_load.c

deleted file mode 100644@@ -1,145 +0,0 @@-#include <stdio.h>-#include <math.h>-#include <stdlib.h>-#include <node_api.h>--#define CHECK(expr) \-  { \-    if ((expr) == 0) { \-      fprintf(stderr, "%s:%d: failed assertion `%s'\n", __FILE__, __LINE__, #expr); \-      fflush(stderr); \-      abort(); \-    } \-  }--// Structure containing information needed for as long as the addon exists. It-// replaces the use of global static data with per-addon-instance data by-// associating an instance of this structure with each instance of this addon-// during addon initialization. The instance of this structure is then passed to-// each binding the addon provides. Thus, the data stored in an instance of this-// structure is available to each binding, just as global static data would be.-typedef struct {-  double value;-} AddonData;--// This is the actual, useful work performed: increment or decrement the value-// stored per addon instance after passing it through a CPU-consuming but-// otherwise useless calculation.-static int ModifyAddonData(AddonData* data, double offset) {-    // Expensively increment or decrement the value.-    data->value = tan(atan(exp(log(sqrt(data->value * data->value))))) + offset;--    // Round the value to the nearest integer.-    data->value =-        (double)(((int)data->value) +-        (data->value - ((double)(int)data->value) > 0.5 ? 1 : 0));--    // Return the value as an integer.-    return (int)(data->value);-}--// This is boilerplate. The instance of the `AddonData` structure created during-// addon initialization must be destroyed when the addon is unloaded. This-// function will be called when the addon's `exports` object is garbage collected.-static void DeleteAddonData(napi_env env, void* data, void* hint) {-  // Avoid unused parameter warnings.-  (void) env;-  (void) hint;--  // Free the per-addon-instance data.-  free(data);-}--// This is also boilerplate. It creates and initializes an instance of the-// `AddonData` structure and ties its lifecycle to that of the addon instance's-// `exports` object. This means that the data will be available to this instance-// of the addon for as long as the JavaScript engine keeps it alive.-static AddonData* CreateAddonData(napi_env env, napi_value exports) {-  AddonData* result = malloc(sizeof(*result));-  result->value = 0.0;-  CHECK(napi_wrap(env,-                   exports,-                   result,-                   DeleteAddonData,-                   NULL,-                   NULL) == napi_ok);-  return result;-}--// This function is called from JavaScript. It uses an expensive operation to-// increment the value stored inside the `AddonData` structure by one.-static napi_value Increment(napi_env env, napi_callback_info info) {-  // Retrieve the per-addon-instance data.-  AddonData* addon_data = NULL;-  CHECK(napi_get_cb_info(env,-                          info,-                          NULL,-                          NULL,-                          NULL,-                          ((void**)&addon_data)) == napi_ok);--  // Increment the per-addon-instance value and create a new JavaScript integer-  // from it.-  napi_value result;-  CHECK(napi_create_int32(env,-                           ModifyAddonData(addon_data, 1.0),-                           &result) == napi_ok);--  // Return the JavaScript integer back to JavaScript.-  return result;-}--// This function is called from JavaScript. It uses an expensive operation to-// decrement the value stored inside the `AddonData` structure by one.-static napi_value Decrement(napi_env env, napi_callback_info info) {-  // Retrieve the per-addon-instance data.-  AddonData* addon_data = NULL;-  CHECK(napi_get_cb_info(env,-                          info,-                          NULL,-                          NULL,-                          NULL,-                          ((void**)&addon_data)) == napi_ok);--  // Decrement the per-addon-instance value and create a new JavaScript integer-  // from it.-  napi_value result;-  CHECK(napi_create_int32(env,-                           ModifyAddonData(addon_data, -1.0),-                           &result) == napi_ok);--  // Return the JavaScript integer back to JavaScript.-  return result;-}--// Initialize the addon in such a way that it may be initialized multiple times-// per process. The function body following this macro is provided the value-// `env` which has type `napi_env` and the value `exports` which has type-// `napi_value` and which refers to a JavaScript object that ultimately contains-// the functions this addon wishes to expose. At the end, it must return a-// `napi_value`. It may return `exports`, or it may create a new `napi_value`-// and return that instead.-NAPI_MODULE_INIT(/*env, exports*/) {-  // Create a new instance of the per-instance-data that will be associated with-  // the instance of the addon being initialized here and that will be destroyed-  // along with the instance of the addon.-  AddonData* addon_data = CreateAddonData(env, exports);--  // Declare the bindings this addon provides. The data created above is given-  // as the last initializer parameter, and will be given to the binding when it-  // is called.-  napi_property_descriptor bindings[] = {-    {"increment", NULL, Increment, NULL, NULL, NULL, napi_enumerable, addon_data},-    {"decrement", NULL, Decrement, NULL, NULL, NULL, napi_enumerable, addon_data}-  };--  // Expose the two bindings declared above to JavaScript.-  CHECK(napi_define_properties(env,-                                exports,-                                sizeof(bindings) / sizeof(bindings[0]),-                                bindings) == napi_ok);--  // Return the `exports` object provided. It now has two new properties, which-  // are the functions we wish to expose to JavaScript.-  return exports;-}

multiple_load/napi/package.json

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "name": "multiple_load",-  "version": "0.0.0",-  "description": "Multiple load example",-  "main": "index.js",-  "private": true,-  "scripts": {-    "test": "node --experimental-worker index.js"-  },-  "engines": {-    "node": ">= 10.10.0"-  },-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.2.1"-  }-}

multiple_load/node_10/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  'targets': [-    {-      'target_name': 'multiple_load',-      'sources': [ 'multiple_load.cc' ]-    }-  ]-}

multiple_load/node_10/index.js

deleted file mode 100644@@ -1,40 +0,0 @@-// Example illustrating the case where a native addon is loaded multiple times.-// This entire file is executed twice, concurrently - once on the main thread,-// and once on a thread launched from the main thread.--// We load the worker threads module, which allows us to launch multiple Node.js-// environments, each in its own thread.-const {-  Worker, isMainThread-} = require('worker_threads');--// We load the native addon.-const addon = require('bindings')('multiple_load');--// The iteration count can be tweaked to ensure that the output from the two-// threads is interleaved. Too few iterations and the output of one thread-// follows the output of the other, not really illustrating the concurrency.-const iterations = 1000;--// This function is an idle loop that performs a random walk from 0 by calling-// into the native addon to either increment or decrement the initial value.-function useAddon(addon, prefix, iterations) {-  if (iterations >= 0) {-    if (Math.random() < 0.5) {-      console.log(prefix + ': new value (decremented): ' + addon.decrement());-    } else {-      console.log(prefix + ': new value (incremented): ' + addon.increment());-    }-    setImmediate(() => useAddon(addon, prefix, --iterations));-  }-}--if (isMainThread) {-  // On the main thread, we launch a worker and wait for it to come online. Then-  // we start the loop.-  (new Worker(__filename)).on('online',-      () => useAddon(addon, "Main thread", iterations));-} else {-  // On the secondary thread we immediately start the loop.-  useAddon(addon, "Worker thread", iterations);-}

multiple_load/node_10/multiple_load.cc

deleted file mode 100644@@ -1,121 +0,0 @@-#include <math.h>-#include <node.h>--using namespace v8;--// Class containing information needed for as long as the addon exists. It-// replaces the use of global static data with per-addon-instance data by-// associating an instance of this class with each instance of this addon during-// addon initialization. The instance of this class is then passed to each-// binding the addon provides. Thus, the data stored in an instance of this-// class is available to each binding, just as global static data would be.-class AddonData {- public:-  // This is the actual, useful work performed: increment or decrement the value-  // stored per addon instance after passing it through a CPU-consuming but-  // otherwise useless calculation. Round the result to the nearest integer.-  int GetNewValue(double offset) {-    // Expensively increment or decrement the value.-    value = tan(atan(exp(log(sqrt(value * value))))) + offset;--    // Round the value to the nearest integer.-    value =-        (double)(((int)value) + (value - ((double)(int)value) > 0.5 ? 1 : 0));--    // Return the value as an integer.-    return (int)value;-  }--  // This is boilerplate. It creates a new instance of this class and wraps it-  // into a v8::External. The isolate and the exports are necessary, because we-  // want the instance of this class to be destroyed along with the exports-  // object when the addon is eventually unloaded.-  static Local<Value> New(Isolate* isolate, Local<Object> exports) {-    return External::New(isolate, new AddonData(isolate, exports));-  }-- private:-  // This is the actual, useful payload carried by an instance of this class.-  // A double value is kept around for as long as an instance of this addon is-  // loaded, and is incremented or decremented whenever the addon receives a-  // call from JavaScript.-  double value;--  explicit AddonData(Isolate* isolate, Local<Object> exports)-      :  // The payload is initialized here. The rest of the constructor is-         // boilerplate that ensures that the instance of this addon data is-         // destroyed along with the instance of this addon (`exports`).-        value(0.0) {-    exports_persistent.Reset(isolate, exports);-    exports_persistent.SetWeak(this, DeleteMe, WeakCallbackType::kParameter);-  }--  // The rest of the class definition is boilerplate.--  // The persistent reference must be reset before the instance of this class is-  // destroyed, otherwise memory will leak on the V8 side.-  ~AddonData() { exports_persistent.Reset(); }--  // This static function will be called when the addon instance is unloaded. It-  // merely destroys the per-addon-instance data.-  static void DeleteMe(const WeakCallbackInfo<AddonData>& info) {-    delete info.GetParameter();-  }--  Persistent<Object> exports_persistent;-};--// Function called from JavaScript to increment the value stored in this addon.-void Increment(const FunctionCallbackInfo<Value>& info) {-  // Retrieve the per-addon-instance data.-  AddonData* addon_data =-      static_cast<AddonData*>(info.Data().As<External>()->Value());--  info.GetReturnValue().Set(-      Number::New(info.GetIsolate(), addon_data->GetNewValue(1.0)));-}--// Function called from JavaScript to decrement the value stored in this addon.-void Decrement(const FunctionCallbackInfo<Value>& info) {-  // Retrieve the per-addon-instance data.-  AddonData* addon_data =-      static_cast<AddonData*>(info.Data().As<External>()->Value());--  info.GetReturnValue().Set(-      Number::New(info.GetIsolate(), addon_data->GetNewValue(-1.0)));-}--// Initialize the addon in such a way that it may be initialized multiple times-// per process. The function body following this macro is provided the value-// `exports` of type `Local<Object>`, the value `module` of type-// `Local<Object>`, and `context` of type `Local<Context>`. It may either define-// new properties on the `exports` object, or define the property named-// "exports" on the `module` object.-NODE_MODULE_INIT(/*exports, module, context*/) {-  Isolate* isolate = context->GetIsolate();--  // Create a new instance of the addon data that will be associated with this-  // instance of the addon, and that will be freed along with this instance of-  // the addon.-  Local<Value> addon_data = AddonData::New(isolate, exports);--  // Export the functions we wish to make available to JavaScript.--  exports-      ->Set(context,-            String::NewFromUtf8(isolate, "increment", NewStringType::kNormal)-                .ToLocalChecked(),-            FunctionTemplate::New(isolate, Increment, addon_data)-                ->GetFunction(context)-                .ToLocalChecked())-      .FromJust();--  exports-      ->Set(context,-            String::NewFromUtf8(isolate, "decrement", NewStringType::kNormal)-                .ToLocalChecked(),-            FunctionTemplate::New(isolate, Decrement, addon_data)-                ->GetFunction(context)-                .ToLocalChecked())-      .FromJust();-}

multiple_load/node_10/package.json

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "name": "multiple_load",-  "version": "0.0.0",-  "description": "Multiple load example",-  "main": "index.js",-  "private": true,-  "scripts": {-    "test": "node --experimental-worker index.js"-  },-  "engines": {-    "node": ">= 10.10.0"-  },-  "gypfile": true,-  "dependencies": {-    "bindings": "~1.2.1"-  }-}

napi-asyncworker-example/node-addon-api/README.md

deleted file mode 100644@@ -1,14 +0,0 @@-# Node-API AsyncWorker Example--This is an example project showing how to use the Node.js Node-API AsyncWorker class--A tutorial describing this project can be found at the [Node-API Resource](https://napi.inspiredware.com/special-topics/asyncworker.html).--To build and run this program on your system, clone it to your computer and run these two commands inside your clone:--```-npm install-npm test-```--> You need to have Node 10.5.0 or later installed. \ No newline at end of file

napi-asyncworker-example/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,20 +0,0 @@-{
-  'targets': [
-    {
-      'target_name': 'napi-asyncworker-example-native',
-      'sources': [ 'src/RunSimpleAsyncWorker.cc', 'src/SimpleAsyncWorker.cc' ],
-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],
-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],
-      'cflags!': [ '-fno-exceptions' ],
-      'cflags_cc!': [ '-fno-exceptions' ],
-      'xcode_settings': {
-        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
-        'CLANG_CXX_LIBRARY': 'libc++',
-        'MACOSX_DEPLOYMENT_TARGET': '10.7'
-      },
-      'msvs_settings': {
-        'VCCLCompilerTool': { 'ExceptionHandling': 1 },
-      }
-    }
-  ]
-}\ No newline at end of file

napi-asyncworker-example/node-addon-api/package.json

deleted file mode 100644@@ -1,23 +0,0 @@-{-  "name": "napi-asyncworker-example",-  "description": "An example project showing how to use the Node.js Node-API AsyncWorker class",-  "version": "1.0.0",-  "main": "test/Test.js",-  "dependencies": {-    "node-addon-api": "^1.1.0"-  },-  "scripts": {-    "test": "node --napi-modules ./test/Test.js"-  },-  "gypfile": true,-  "keywords": [-    "node",-    "napi",-    "n-api",-    "async",-    "asyncworker",-    "example"-  ],-  "author": "Jim Schlight",-  "license": "MIT"-}

napi-asyncworker-example/node-addon-api/src/RunSimpleAsyncWorker.cc

deleted file mode 100644@@ -1,19 +0,0 @@-#include "SimpleAsyncWorker.h"
-
-Value runSimpleAsyncWorker(const CallbackInfo& info) {
-  int runTime = info[0].As<Number>();
-  Function callback = info[1].As<Function>();
-  SimpleAsyncWorker* asyncWorker = new SimpleAsyncWorker(callback, runTime);
-  asyncWorker->Queue();
-  std::string msg =
-      "SimpleAsyncWorker for " + std::to_string(runTime) + " seconds queued.";
-  return String::New(info.Env(), msg.c_str());
-};
-
-Object Init(Env env, Object exports) {
-  exports["runSimpleAsyncWorker"] = Function::New(
-      env, runSimpleAsyncWorker, std::string("runSimpleAsyncWorker"));
-  return exports;
-}
-
-NODE_API_MODULE(addon, Init)\ No newline at end of file

napi-asyncworker-example/node-addon-api/src/SimpleAsyncWorker.cc

deleted file mode 100644@@ -1,17 +0,0 @@-#include "SimpleAsyncWorker.h"
-#include <chrono>
-#include <thread>
-
-SimpleAsyncWorker::SimpleAsyncWorker(Function& callback, int runTime)
-    : AsyncWorker(callback), runTime(runTime){};
-
-void SimpleAsyncWorker::Execute() {
-  std::this_thread::sleep_for(std::chrono::seconds(runTime));
-  if (runTime == 4) SetError("Oops! Failed after 'working' 4 seconds.");
-};
-
-void SimpleAsyncWorker::OnOK() {
-  std::string msg = "SimpleAsyncWorker returning after 'working' " +
-                    std::to_string(runTime) + " seconds.";
-  Callback().Call({Env().Null(), String::New(Env(), msg)});
-};\ No newline at end of file

napi-asyncworker-example/node-addon-api/src/SimpleAsyncWorker.h

deleted file mode 100644@@ -1,15 +0,0 @@-#pragma once
-#include <napi.h>
-using namespace Napi;
-
-class SimpleAsyncWorker : public AsyncWorker {
- public:
-  SimpleAsyncWorker(Function& callback, int runTime);
-  virtual ~SimpleAsyncWorker(){};
-
-  void Execute();
-  void OnOK();
-
- private:
-  int runTime;
-};\ No newline at end of file

napi-asyncworker-example/node-addon-api/test/Test.js

deleted file mode 100644@@ -1,18 +0,0 @@-const runWorker = require('../build/Release/napi-asyncworker-example-native');
-
-let result = runWorker.runSimpleAsyncWorker(2, AsyncWorkerCompletion);
-console.log("runSimpleAsyncWorker returned '"+result+"'.");
-
-result = runWorker.runSimpleAsyncWorker(4, AsyncWorkerCompletion);
-console.log("runSimpleAsyncWorker returned '"+result+"'.");
-
-result = runWorker.runSimpleAsyncWorker(8, AsyncWorkerCompletion);
-console.log("runSimpleAsyncWorker returned '"+result+"'.");
-
-function AsyncWorkerCompletion (err, result) {
-    if (err) {
-        console.log("SimpleAsyncWorker returned an error: ", err);
-    } else {
-        console.log("SimpleAsyncWorker returned '"+result+"'.");
-    }
-};

object-template-demo/README.md

deleted file mode 100644@@ -1,3 +0,0 @@-The goal of this demo is to show how to implement V8 ObjectTemplate-like handlers.-NAN uses the ObjectTemplate directly: the code is adapted from NAN namedinterceptors unit test.-Node-API cannot use the ObjectTemplate: it uses the JavaScript Proxy object to get similar behavior.

object-template-demo/nan/binding.gyp

deleted file mode 100644@@ -1,11 +0,0 @@-{-  "targets": [-    {-      "target_name": "object-template-demo",-      "sources": [ "object-template-demo.cc" ],-      "include_dirs": [-        "<!(node -e \"require('nan')\")"-      ]-    }-  ]-}

object-template-demo/nan/index.js

deleted file mode 100644@@ -1,10 +0,0 @@-const addon = require('bindings')('object-template-demo');--const interceptor = addon.create();-console.log(interceptor.prop); // 'foo'-interceptor.prop = 'setting a value';-console.log(interceptor.prop); // 'setting a value'-delete interceptor.something;-console.log(interceptor.prop); // 'goober';-console.log(Object.prototype.hasOwnProperty.call(interceptor, "thing")); // true-console.log(Object.keys(interceptor)[0]); // 'value'

object-template-demo/nan/object-template-demo.cc

deleted file mode 100644@@ -1,122 +0,0 @@-/*********************************************************************- * NAN - Native Abstractions for Node.js- *- * Copyright (c) 2018 NAN contributors- *- * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>- ********************************************************************/--#include <nan.h>-#include <cstring>--using namespace Nan;  // NOLINT(build/namespaces)--class NamedInterceptor : public ObjectWrap {-  char buf[256];-- public:-  NamedInterceptor() { std::strncpy(this->buf, "foo", sizeof (this->buf)); }-  static NAN_MODULE_INIT(Init);-  static v8::Local<v8::Value> NewInstance ();-  static NAN_METHOD(New);--  static NAN_PROPERTY_GETTER(PropertyGetter);-  static NAN_PROPERTY_SETTER(PropertySetter);-  static NAN_PROPERTY_ENUMERATOR(PropertyEnumerator);-  static NAN_PROPERTY_DELETER(PropertyDeleter);-  static NAN_PROPERTY_QUERY(PropertyQuery);-};--static Persistent<v8::FunctionTemplate> namedinterceptors_constructor;--NAN_METHOD(CreateNew) {-  info.GetReturnValue().Set(NamedInterceptor::NewInstance());-}--NAN_MODULE_INIT(NamedInterceptor::Init) {-  v8::Local<v8::FunctionTemplate> tpl =-    Nan::New<v8::FunctionTemplate>(NamedInterceptor::New);-  namedinterceptors_constructor.Reset(tpl);-  tpl->SetClassName(Nan::New("NamedInterceptor").ToLocalChecked());-  tpl->InstanceTemplate()->SetInternalFieldCount(1);-  v8::Local<v8::ObjectTemplate> inst = tpl->InstanceTemplate();--  SetNamedPropertyHandler(-      inst-    , NamedInterceptor::PropertyGetter-    , NamedInterceptor::PropertySetter-    , NamedInterceptor::PropertyQuery-    , NamedInterceptor::PropertyDeleter-    , NamedInterceptor::PropertyEnumerator);--  v8::Local<v8::Function> createnew =-    Nan::GetFunction(Nan::New<v8::FunctionTemplate>(CreateNew))-    .ToLocalChecked();-  Set(target, Nan::New("create").ToLocalChecked(), createnew);-}--v8::Local<v8::Value> NamedInterceptor::NewInstance () {-  EscapableHandleScope scope;-  v8::Local<v8::FunctionTemplate> constructorHandle =-      Nan::New(namedinterceptors_constructor);-  v8::Local<v8::Object> instance =-    Nan::NewInstance(GetFunction(constructorHandle).ToLocalChecked())-    .ToLocalChecked();-  return scope.Escape(instance);-}--NAN_METHOD(NamedInterceptor::New) {-  NamedInterceptor* interceptor = new NamedInterceptor();-  interceptor->Wrap(info.This());-  info.GetReturnValue().Set(info.This());-}---NAN_PROPERTY_GETTER(NamedInterceptor::PropertyGetter) {-  NamedInterceptor* interceptor =-    ObjectWrap::Unwrap<NamedInterceptor>(info.Holder());-  if (!std::strcmp(*Nan::Utf8String(property), "prop")) {-    info.GetReturnValue().Set(Nan::New(interceptor->buf).ToLocalChecked());-  } else {-    info.GetReturnValue().Set(Nan::New("bar").ToLocalChecked());-  }-}--NAN_PROPERTY_SETTER(NamedInterceptor::PropertySetter) {-  NamedInterceptor* interceptor =-    ObjectWrap::Unwrap<NamedInterceptor>(info.Holder());-  if (!std::strcmp(*Nan::Utf8String(property), "prop")) {-    std::strncpy(-        interceptor->buf-      , *Nan::Utf8String(value)-      , sizeof (interceptor->buf));-    info.GetReturnValue().Set(info.This());-  } else {-    info.GetReturnValue().Set(info.This());-  }-}--NAN_PROPERTY_ENUMERATOR(NamedInterceptor::PropertyEnumerator) {-  v8::Local<v8::Array> arr = Nan::New<v8::Array>();-  Set(arr, 0, Nan::New("value").ToLocalChecked());-  info.GetReturnValue().Set(arr);-}--NAN_PROPERTY_DELETER(NamedInterceptor::PropertyDeleter) {-  NamedInterceptor* interceptor =-    ObjectWrap::Unwrap<NamedInterceptor>(info.Holder());-  std::strncpy(interceptor->buf, "goober", sizeof (interceptor->buf));-  info.GetReturnValue().Set(True());-}--NAN_PROPERTY_QUERY(NamedInterceptor::PropertyQuery) {-  Nan::Utf8String s(property);-  if (!std::strcmp(*s, "thing")) {-    return info.GetReturnValue().Set(Nan::New<v8::Integer>(v8::DontEnum));-  }-  if (!std::strcmp(*s, "value")) {-    return info.GetReturnValue().Set(Nan::New(0));-  }-}--NODE_MODULE(namedinterceptors, NamedInterceptor::Init)

object-template-demo/nan/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "object-template-demo",-  "version": "0.0.0",-  "description": "Intercept named property access using V8 ObjectTemplate",-  "main": "index.js",-  "private": true,-  "gypfile": true,-  "scripts": {-    "test": "node index.js"-  },-  "dependencies": {-    "bindings": "~1.5.0",-    "nan": "^2.14.0"-  }-}

object-template-demo/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  "targets": [-    {-      "target_name": "object_template_demo",-      "sources": [ "object-template-demo.cc", "proxy-template.cc" ]-    }-  ]-}

object-template-demo/napi/index.js

deleted file mode 100644@@ -1,10 +0,0 @@-const addon = require('bindings')('object_template_demo');--const interceptor = addon.create();-console.log(interceptor.prop); // 'foo'-interceptor.prop = 'setting a value';-console.log(interceptor.prop); // 'setting a value'-delete interceptor.something;-console.log(interceptor.prop); // 'goober';-console.log(Object.prototype.hasOwnProperty.call(interceptor, "thing")); // true-console.log(Object.keys(interceptor)[0]); // 'value'

object-template-demo/napi/node-api-common.h

deleted file mode 100644@@ -1,141 +0,0 @@-#include <node_api.h>-#include <initializer_list>-#include <utility>--// Empty value so that macros here are able to return NULL or void-#define NODE_API_RETVAL_NOTHING  // Intentionally blank #define--#define GET_AND_THROW_LAST_ERROR(env)                                          \-  do {                                                                         \-    const napi_extended_error_info* error_info;                                \-    napi_get_last_error_info((env), &error_info);                              \-    bool is_pending;                                                           \-    const char* err_message = error_info->error_message;                       \-    napi_is_exception_pending((env), &is_pending);                             \-    /* If an exception is already pending, don't rethrow it */                 \-    if (!is_pending) {                                                         \-      const char* error_message =                                              \-          err_message != NULL ? err_message : "empty error message";           \-      napi_throw_error((env), NULL, error_message);                            \-    }                                                                          \-  } while (0)--#define NODE_API_ASSERT_BASE(env, assertion, message, ret_val)                 \-  do {                                                                         \-    if (!(assertion)) {                                                        \-      napi_throw_error(                                                        \-          (env), NULL, "assertion (" #assertion ") failed: " message);         \-      return ret_val;                                                          \-    }                                                                          \-  } while (0)--// Returns NULL on failed assertion.-// This is meant to be used inside napi_callback methods.-#define NODE_API_ASSERT(env, assertion, message)                               \-  NODE_API_ASSERT_BASE(env, assertion, message, NULL)--#define NODE_API_CALL_BASE(env, the_call, ret_val)                             \-  do {                                                                         \-    if ((the_call) != napi_ok) {                                               \-      GET_AND_THROW_LAST_ERROR((env));                                         \-      return ret_val;                                                          \-    }                                                                          \-  } while (0)--// Returns NULL if the_call doesn't return napi_ok.-#define NODE_API_CALL(env, the_call) NODE_API_CALL_BASE(env, the_call, NULL)--// Returns empty if the_call doesn't return napi_ok.-#define NODE_API_CALL_RETURN_VOID(env, the_call)                               \-  NODE_API_CALL_BASE(env, the_call, NODE_API_RETVAL_NOTHING)--#define CHECK_NAPI(...)                                                        \-  do {                                                                         \-    napi_status res__ = (__VA_ARGS__);                                         \-    if (res__ != napi_ok) {                                                    \-      return res__;                                                            \-    }                                                                          \-  } while (0)--#define NAPI_CALL(expr) NODE_API_CALL(env, expr);--#ifdef __cpp_lib_span-#include <span>-using std::span;-#else-/**- * @brief A span of values that can be used to pass arguments to function.- *- * For C++20 we should consider to replace it with std::span.- */-template <typename T>-struct span {-  constexpr span(std::initializer_list<T> il) noexcept-      : data_{const_cast<T*>(il.begin())}, size_{il.size()} {}-  constexpr span(T* data, size_t size) noexcept : data_{data}, size_{size} {}-  [[nodiscard]] constexpr T* data() const noexcept { return data_; }-  [[nodiscard]] constexpr size_t size() const noexcept { return size_; }-  [[nodiscard]] constexpr T* begin() const noexcept { return data_; }-  [[nodiscard]] constexpr T* end() const noexcept { return data_ + size_; }-  const T& operator[](size_t index) const noexcept { return *(data_ + index); }-- private:-  T* data_;-  size_t size_;-};-#endif  // __cpp_lib_span--struct RefHolder {-  RefHolder(std::nullptr_t = nullptr) noexcept {}-  explicit RefHolder(napi_env env, napi_value value) : env_(env) {-    // Start with 2 to avoid ever going to 0 that creates a weak ref.-    napi_create_reference(env, value, 2, &ref_);-  }--  // The class is movable.-  RefHolder(RefHolder&& other) noexcept-      : env_(std::exchange(other.env_, nullptr)),-        ref_(std::exchange(other.ref_, nullptr)) {}--  RefHolder& operator=(RefHolder&& other) noexcept {-    if (this != &other) {-      swap(*this, other);-      RefHolder temp(std::move(other));-    }-    return *this;-  }--  // The class is not copyable.-  RefHolder(const RefHolder& other) = delete;-  RefHolder& operator=(const RefHolder& other) = delete;--  ~RefHolder() noexcept {-    if (env_ != nullptr && ref_ != nullptr) {-      uint32_t refCount{};-      napi_reference_unref(env_, ref_, &refCount);-      if (refCount == 1) {-        napi_delete_reference(env_, ref_);-      }-    }-  }--  operator napi_value() const {-    napi_value result{};-    if (ref_ != nullptr) {-      napi_get_reference_value(env_, ref_, &result);-    }-    return result;-  }--  explicit operator bool() const noexcept { return ref_ != nullptr; }--  friend void swap(RefHolder& left, RefHolder& right) noexcept {-    using std::swap;-    swap(left.env_, right.env_);-    swap(left.ref_, right.ref_);-  }-- private:-  napi_env env_{};-  napi_ref ref_{};-};

object-template-demo/napi/object-template-demo.cc

deleted file mode 100644@@ -1,306 +0,0 @@-#include <memory>-#include <cstring>-#include <string>-#include "proxy-template.h"--struct InstanceData {-  RefHolder constructor_;-  std::unique_ptr<ProxyTemplate> proxyTemplate_;-};--class NamedInterceptor {-  char buf[256];-- public:-  NamedInterceptor() { std::strncpy(this->buf, "foo", sizeof(this->buf)); }-  static napi_value Init(napi_env env, napi_value exports);-  static napi_value Constructor(napi_env env);-  static napi_value NewInstance(napi_env env);-  static napi_value New(napi_env env, napi_callback_info info);-  static napi_value CreateNew(napi_env env, napi_callback_info info);--  static napi_status ToUtf8String(napi_env env,-                                  napi_value value,-                                  std::string* result);-  static napi_status PropertyGetter(napi_env env,-                                    napi_value target,-                                    napi_value key,-                                    napi_value receiver,-                                    napi_value* result);-  static napi_status PropertySetter(napi_env env,-                                    napi_value target,-                                    napi_value key,-                                    napi_value value,-                                    napi_value receiver,-                                    bool* result);-  static napi_status PropertyDeleter(napi_env env,-                                     napi_value target,-                                     napi_value key,-                                     bool* result);-  static napi_status PropertyQuery(napi_env env,-                                   napi_value target,-                                   napi_value key,-                                   bool* result);-  static napi_status GetOwnPropertyDescriptor(napi_env env,-                                              napi_value target,-                                              napi_value key,-                                              napi_value* result);-  static napi_status OwnKeys(napi_env env,-                             napi_value target,-                             napi_value* result);-};--napi_value NamedInterceptor::CreateNew(napi_env env, napi_callback_info info) {-  return NamedInterceptor::NewInstance(env);-}--napi_value NamedInterceptor::Init(napi_env env, napi_value exports) {-  napi_value constructor{};-  NAPI_CALL(napi_define_class(env,-                              "NamedInterceptor",-                              NAPI_AUTO_LENGTH,-                              NamedInterceptor::New,-                              nullptr,-                              0,-                              nullptr,-                              &constructor));--  ProxyHandlerBuilder handlerBuilder{};-  NAPI_CALL(handlerBuilder.Get(env, &PropertyGetter));-  NAPI_CALL(handlerBuilder.Set(env, &PropertySetter));-  NAPI_CALL(handlerBuilder.DeleteProperty(env, &PropertyDeleter));-  NAPI_CALL(handlerBuilder.Has(env, &PropertyQuery));-  NAPI_CALL(-      handlerBuilder.GetOwnPropertyDescriptor(env, &GetOwnPropertyDescriptor));-  NAPI_CALL(handlerBuilder.OwnKeys(env, &OwnKeys));-  napi_value proxyHandler{};-  NAPI_CALL(handlerBuilder.NewHandler(env, &proxyHandler));-  NAPI_CALL(napi_set_instance_data(-      env,-      new InstanceData{RefHolder(env, constructor),-                       std::make_unique<ProxyTemplate>(env, proxyHandler)},-      [](napi_env /*env*/, void* data, void* /*hint*/) {-        delete static_cast<InstanceData*>(data);-      },-      nullptr));--  napi_value createFunc{};-  NAPI_CALL(napi_create_function(-      env, "create", NAPI_AUTO_LENGTH, CreateNew, nullptr, &createFunc));--  NAPI_CALL(napi_set_named_property(env, exports, "create", createFunc));-  return exports;-}--napi_value NamedInterceptor::Constructor(napi_env env) {-  InstanceData* instanceData{};-  NAPI_CALL(-      napi_get_instance_data(env, reinterpret_cast<void**>(&instanceData)));-  return instanceData->constructor_;-}--napi_value NamedInterceptor::NewInstance(napi_env env) {-  napi_escapable_handle_scope scope{};-  NAPI_CALL(napi_open_escapable_handle_scope(env, &scope));--  napi_value instance{};-  NAPI_CALL(napi_new_instance(env, Constructor(env), 0, nullptr, &instance));--  napi_value result{};-  NAPI_CALL(napi_escape_handle(env, scope, instance, &result));-  NAPI_CALL(napi_close_escapable_handle_scope(env, scope));-  return result;-}--napi_value NamedInterceptor::New(napi_env env, napi_callback_info info) {-  napi_value newTarget{};-  NAPI_CALL(napi_get_new_target(env, info, &newTarget));-  NODE_API_ASSERT_BASE(-      env, newTarget != nullptr, "Must be invoked as a constructor.", nullptr);--  napi_value proxyTarget{}, result{};-  NAPI_CALL(napi_create_function(-      env,-      "target",-      NAPI_AUTO_LENGTH,-      [](napi_env, napi_callback_info) -> napi_value { return nullptr; },-      nullptr,-      &proxyTarget));--  NamedInterceptor* obj = new NamedInterceptor();--  NAPI_CALL(napi_wrap(-      env,-      proxyTarget,-      obj,-      [](napi_env /*env*/, void* data, void* /*hint*/) {-        delete reinterpret_cast<NamedInterceptor*>(data);-      },-      nullptr,-      nullptr));--  InstanceData* instanceData{};-  NAPI_CALL(-      napi_get_instance_data(env, reinterpret_cast<void**>(&instanceData)));-  NAPI_CALL(-      instanceData->proxyTemplate_->NewInstance(env, proxyTarget, &result));-  return result;-}--napi_status NamedInterceptor::ToUtf8String(napi_env env,-                                           napi_value value,-                                           std::string* result) {-  size_t size{};-  CHECK_NAPI(napi_get_value_string_utf8(env, value, nullptr, 0, &size));-  result->assign(size, ' ');-  return napi_get_value_string_utf8(-      env, value, &(*result)[0], size + 1, nullptr);-}--napi_status NamedInterceptor::PropertyGetter(napi_env env,-                                             napi_value target,-                                             napi_value key,-                                             napi_value receiver,-                                             napi_value* result) {-  NamedInterceptor* interceptor{};-  CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));-  std::string keyStr;-  CHECK_NAPI(ToUtf8String(env, key, &keyStr));-  if (keyStr == "prop") {-    return napi_create_string_utf8(-        env, interceptor->buf, NAPI_AUTO_LENGTH, result);-  } else {-    return napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, result);-  }-}--napi_status NamedInterceptor::PropertySetter(napi_env env,-                                             napi_value target,-                                             napi_value key,-                                             napi_value value,-                                             napi_value receiver,-                                             bool* result) {-  NamedInterceptor* interceptor{};-  CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));-  std::string keyStr;-  CHECK_NAPI(ToUtf8String(env, key, &keyStr));-  if (keyStr == "prop") {-    std::string valueStr;-    CHECK_NAPI(ToUtf8String(env, value, &valueStr));-    std::strncpy(interceptor->buf, valueStr.data(), sizeof(interceptor->buf));-    *result = true;-  } else {-    *result = false;-  }-  return napi_ok;-}--napi_status NamedInterceptor::PropertyDeleter(napi_env env,-                                              napi_value target,-                                              napi_value key,-                                              bool* result) {-  NamedInterceptor* interceptor{};-  CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));-  std::strncpy(interceptor->buf, "goober", sizeof(interceptor->buf));-  *result = true;-  return napi_ok;-}--napi_status NamedInterceptor::PropertyQuery(napi_env env,-                                            napi_value target,-                                            napi_value key,-                                            bool* result) {-  std::string keyStr;-  CHECK_NAPI(ToUtf8String(env, key, &keyStr));--  if (keyStr == "thing") {-    *result = true;-  }-  if (keyStr == "value") {-    *result = true;-  }-  return napi_ok;-}--napi_status NamedInterceptor::GetOwnPropertyDescriptor(napi_env env,-                                                       napi_value target,-                                                       napi_value key,-                                                       napi_value* result) {-  std::string keyStr;-  CHECK_NAPI(ToUtf8String(env, key, &keyStr));--  if (keyStr == "thing") {-    CHECK_NAPI(napi_create_object(env, result));-    napi_value trueValue{};-    CHECK_NAPI(napi_get_boolean(env, true, &trueValue));-    CHECK_NAPI(-        napi_set_named_property(env, *result, "configurable", trueValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));-  }-  if (keyStr == "value") {-    CHECK_NAPI(napi_create_object(env, result));-    napi_value trueValue{};-    CHECK_NAPI(napi_get_boolean(env, true, &trueValue));-    CHECK_NAPI(-        napi_set_named_property(env, *result, "configurable", trueValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", trueValue));-  }-  if (keyStr == "arguments" || keyStr == "caller") {-    CHECK_NAPI(napi_create_object(env, result));-    napi_value trueValue{}, falseValue{};-    CHECK_NAPI(napi_get_boolean(env, false, &falseValue));-    CHECK_NAPI(napi_get_boolean(env, false, &trueValue));-    CHECK_NAPI(-        napi_set_named_property(env, *result, "configurable", falseValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "writable", falseValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", falseValue));-    napi_value nullValue{};-    CHECK_NAPI(napi_get_null(env, &nullValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "value", nullValue));-  }-  if (keyStr == "prototype") {-    CHECK_NAPI(napi_create_object(env, result));-    napi_value trueValue{}, falseValue{};-    CHECK_NAPI(napi_get_boolean(env, false, &falseValue));-    CHECK_NAPI(napi_get_boolean(env, true, &trueValue));-    CHECK_NAPI(-        napi_set_named_property(env, *result, "configurable", falseValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", falseValue));-    napi_value nullValue{};-    CHECK_NAPI(napi_get_null(env, &nullValue));-    CHECK_NAPI(napi_set_named_property(env, *result, "value", nullValue));-  }-  return napi_ok;-}--napi_status NamedInterceptor::OwnKeys(napi_env env,-                                      napi_value target,-                                      napi_value* result) {-  CHECK_NAPI(napi_get_all_property_names(env,-                                         target,-                                         napi_key_own_only,-                                         napi_key_all_properties,-                                         napi_key_keep_numbers,-                                         result));--  uint32_t arraySize{};-  CHECK_NAPI(napi_get_array_length(env, *result, &arraySize));-  napi_value firstElement{};-  CHECK_NAPI(napi_get_element(env, *result, 0, &firstElement));-  CHECK_NAPI(napi_set_element(env, *result, arraySize, firstElement));-  napi_value arraySizeValue{};-  CHECK_NAPI(napi_create_uint32(env, arraySize, &arraySizeValue));-  CHECK_NAPI(napi_set_named_property(env, *result, "length", arraySizeValue));-  napi_value value{};-  CHECK_NAPI(napi_create_string_utf8(env, "value", NAPI_AUTO_LENGTH, &value));-  CHECK_NAPI(napi_set_element(env, *result, 0, value));-  return napi_ok;-}--extern "C" napi_value Init(napi_env env, napi_value exports) {-  return NamedInterceptor::Init(env, exports);-}--NAPI_MODULE(NODE_GYP_MODULE_NAME, Init);

object-template-demo/napi/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "object_template_demo",-  "version": "0.0.0",-  "description": "Intercept named property access using Proxy",-  "main": "index.js",-  "private": true,-  "gypfile": true,-  "scripts": {-    "test": "node index.js"-  },-  "dependencies": {-    "bindings": "~1.5.0"-  }-}

object-template-demo/napi/proxy-template.cc

deleted file mode 100644@@ -1,726 +0,0 @@-#include "proxy-template.h"-#include <vector>--namespace {--static napi_status SetTrap(napi_env env,-                           napi_value handler,-                           const char* propertyName,-                           napi_value trap) noexcept {-  if (trap != nullptr) {-    CHECK_NAPI(napi_set_named_property(env, handler, propertyName, trap));-  }-  return napi_ok;-}--using TrapCaller = napi_status (*)(napi_env env,-                                   void* trap,-                                   napi_span<napi_value> args,-                                   napi_value* result);--struct TrapCallInfo {-  TrapCaller Caller;-  void* trap;-};--template <size_t argCount>-napi_callback CreateTrapCallback() noexcept {-  return [](napi_env env, napi_callback_info info) noexcept -> napi_value {-    TrapCallInfo* trapCallInfo{};-    napi_value args[argCount]{};-    size_t actualArgCount{argCount};-    NAPI_CALL(napi_get_cb_info(env,-                               info,-                               &actualArgCount,-                               args,-                               nullptr,-                               reinterpret_cast<void**>(&trapCallInfo)));-    NODE_API_ASSERT_BASE(env,-                         actualArgCount == argCount,-                         "proxy trap requires argCount arguments.",-                         nullptr);-    napi_value result{};-    NAPI_CALL(trapCallInfo->Caller(-        env, trapCallInfo->trap, span<napi_value>(args, argCount), &result));-    return result;-  };-}--napi_status ToVector(napi_env env,-                     napi_value arrayValue,-                     std::vector<napi_value>* result) {-  bool isArray{};-  CHECK_NAPI(napi_is_array(env, arrayValue, &isArray));-  if (isArray) {-    uint32_t arraySize{};-    CHECK_NAPI(napi_get_array_length(env, arrayValue, &arraySize));-    result->reserve(result->size() + arraySize);-    for (uint32_t i = 0; i < arraySize; ++i) {-      napi_value arrayElement{};-      CHECK_NAPI(napi_get_element(env, arrayValue, i, &arrayElement));-      result->push_back(arrayElement);-    }-  }-  return napi_ok;-}--}  // namespace--napi_status ProxyHandlerBuilder::NewHandler(napi_env env,-                                            napi_value* result) noexcept {-  CHECK_NAPI(napi_create_object(env, result));--  CHECK_NAPI(SetTrap(env, *result, "apply", apply_));-  CHECK_NAPI(SetTrap(env, *result, "construct", construct_));-  CHECK_NAPI(SetTrap(env, *result, "defineProperty", defineProperty_));-  CHECK_NAPI(SetTrap(env, *result, "deleteProperty", deleteProperty_));-  CHECK_NAPI(SetTrap(env, *result, "get", get_));-  CHECK_NAPI(SetTrap(-      env, *result, "getOwnPropertyDescriptor", getOwnPropertyDescriptor_));-  CHECK_NAPI(SetTrap(env, *result, "getPrototypeOf", getPrototypeOf_));-  CHECK_NAPI(SetTrap(env, *result, "has", has_));-  CHECK_NAPI(SetTrap(env, *result, "isExtensible", isExtensible_));-  CHECK_NAPI(SetTrap(env, *result, "ownKeys", ownKeys_));-  CHECK_NAPI(SetTrap(env, *result, "preventExtensions", preventExtensions_));-  CHECK_NAPI(SetTrap(env, *result, "set", set_));-  CHECK_NAPI(SetTrap(env, *result, "setPrototypeOf", setPrototypeOf_));-  return napi_ok;-}--napi_value ProxyHandlerBuilder::Apply() noexcept {-  return apply_;-}--void ProxyHandlerBuilder::Apply(napi_value trap) noexcept {-  apply_ = trap;-}--napi_status ProxyHandlerBuilder::Apply(napi_env env,-                                       napi_callback trap,-                                       void* data) noexcept {-  return napi_create_function(-      env, "apply", NAPI_AUTO_LENGTH, trap, data, &apply_);-}--napi_status ProxyHandlerBuilder::Apply(-    napi_env env,-    napi_status (*trap)(napi_env env,-                        napi_value target,-                        napi_value thisArg,-                        napi_value argumentList,-                        napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], args[2], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return Apply(env, CreateTrapCallback<3>(), &callInfo);-}--napi_status ProxyHandlerBuilder::Apply(-    napi_env env,-    napi_status (*trap)(napi_env env,-                        napi_value target,-                        napi_value thisArg,-                        napi_span<napi_value> argumentList,-                        napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{-      [](napi_env env,-         void* trap,-         napi_span<napi_value> args,-         napi_value* result) noexcept {-        std::vector<napi_value> argVector;-        CHECK_NAPI(ToVector(env, args[2], &argVector));-        return reinterpret_cast<TrapType>(trap)(-            env,-            args[0],-            args[1],-            span<napi_value>(argVector.data(), argVector.size()),-            result);-      },-      reinterpret_cast<void*>(trap)};-  return Apply(env, CreateTrapCallback<3>(), &callInfo);-}--napi_value ProxyHandlerBuilder::Construct() noexcept {-  return construct_;-}--void ProxyHandlerBuilder::Construct(napi_value trap) noexcept {-  construct_ = trap;-}--napi_status ProxyHandlerBuilder::Construct(napi_env env,-                                           napi_callback trap,-                                           void* data) noexcept {-  return napi_create_function(-      env, "construct", NAPI_AUTO_LENGTH, trap, data, &construct_);-}--napi_status ProxyHandlerBuilder::Construct(-    napi_env env,-    napi_status (*trap)(napi_env env,-                        napi_value target,-                        napi_value argumentList,-                        napi_value newTarget,-                        napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], args[2], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return Construct(env, CreateTrapCallback<3>(), &callInfo);-}--napi_status ProxyHandlerBuilder::Construct(-    napi_env env,-    napi_status (*trap)(napi_env env,-                        napi_value target,-                        napi_span<napi_value> argumentList,-                        napi_value newTarget,-                        napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{-      [](napi_env env,-         void* trap,-         napi_span<napi_value> args,-         napi_value* result) noexcept {-        std::vector<napi_value> argVector;-        CHECK_NAPI(ToVector(env, args[1], &argVector));-        return reinterpret_cast<TrapType>(trap)(-            env,-            args[0],-            span<napi_value>(argVector.data(), argVector.size()),-            args[2],-            result);-      },-      reinterpret_cast<void*>(trap)};-  return Construct(env, CreateTrapCallback<3>(), &callInfo);-}--napi_value ProxyHandlerBuilder::DefineProperty() noexcept {-  return defineProperty_;-}--void ProxyHandlerBuilder::DefineProperty(napi_value trap) noexcept {-  defineProperty_ = trap;-}--napi_status ProxyHandlerBuilder::DefineProperty(napi_env env,-                                                napi_callback trap,-                                                void* data) noexcept {-  return napi_create_function(-      env, "defineProperty", NAPI_AUTO_LENGTH, trap, data, &defineProperty_);-}--napi_status ProxyHandlerBuilder::DefineProperty(-    napi_env env,-    napi_status (*trap)(napi_env env,-                        napi_value target,-                        napi_value key,-                        napi_value descriptor,-                        napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], args[2], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return DefineProperty(env, CreateTrapCallback<3>(), &callInfo);-}--napi_status ProxyHandlerBuilder::DefineProperty(-    napi_env env,-    napi_status (*trap)(napi_env env,-                        napi_value target,-                        napi_value key,-                        napi_value descriptor,-                        bool* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{-      [](napi_env env,-         void* trap,-         napi_span<napi_value> args,-         napi_value* result) noexcept {-        bool boolResult{};-        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(-            env, args[0], args[1], args[2], &boolResult));-        return napi_get_boolean(env, boolResult, result);-      },-      reinterpret_cast<void*>(trap)};-  return DefineProperty(env, CreateTrapCallback<3>(), &callInfo);-}--napi_value ProxyHandlerBuilder::DeleteProperty() noexcept {-  return deleteProperty_;-}--void ProxyHandlerBuilder::DeleteProperty(napi_value trap) noexcept {-  deleteProperty_ = trap;-}--napi_status ProxyHandlerBuilder::DeleteProperty(napi_env env,-                                                napi_callback trap,-                                                void* data) noexcept {-  return napi_create_function(-      env, "deleteProperty", NAPI_AUTO_LENGTH, trap, data, &deleteProperty_);-}--napi_status ProxyHandlerBuilder::DeleteProperty(-    napi_env env,-    napi_status (*trap)(-        napi_env env, napi_value target, napi_value key, napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return DeleteProperty(env, CreateTrapCallback<2>(), &callInfo);-}--napi_status ProxyHandlerBuilder::DeleteProperty(-    napi_env env,-    napi_status (*trap)(-        napi_env env, napi_value target, napi_value key, bool* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 bool boolResult{};-                                 CHECK_NAPI(reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], &boolResult));-                                 return napi_get_boolean(-                                     env, boolResult, result);-                               },-                               reinterpret_cast<void*>(trap)};-  return DeleteProperty(env, CreateTrapCallback<2>(), &callInfo);-}--napi_value ProxyHandlerBuilder::Get() noexcept {-  return get_;-}--void ProxyHandlerBuilder::Get(napi_value trap) noexcept {-  get_ = trap;-}--napi_status ProxyHandlerBuilder::Get(napi_env env,-                                     napi_callback trap,-                                     void* data) noexcept {-  return napi_create_function(env, "get", NAPI_AUTO_LENGTH, trap, data, &get_);-}--napi_status ProxyHandlerBuilder::Get(napi_env env,-                                     napi_status (*trap)(napi_env env,-                                                         napi_value target,-                                                         napi_value key,-                                                         napi_value receiver,-                                                         napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], args[2], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return Get(env, CreateTrapCallback<3>(), &callInfo);-}--napi_value ProxyHandlerBuilder::GetOwnPropertyDescriptor() noexcept {-  return getOwnPropertyDescriptor_;-}--void ProxyHandlerBuilder::GetOwnPropertyDescriptor(napi_value trap) noexcept {-  getOwnPropertyDescriptor_ = trap;-}--napi_status ProxyHandlerBuilder::GetOwnPropertyDescriptor(napi_env env,-                                                          napi_callback trap,-                                                          void* data) noexcept {-  return napi_create_function(env,-                              "getOwnPropertyDescriptor",-                              NAPI_AUTO_LENGTH,-                              trap,-                              data,-                              &getOwnPropertyDescriptor_);-}--napi_status ProxyHandlerBuilder::GetOwnPropertyDescriptor(-    napi_env env,-    napi_status (*trap)(-        napi_env env, napi_value target, napi_value key, napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return GetOwnPropertyDescriptor(env, CreateTrapCallback<2>(), &callInfo);-}--napi_value ProxyHandlerBuilder::GetPrototypeOf() noexcept {-  return getPrototypeOf_;-}--void ProxyHandlerBuilder::GetPrototypeOf(napi_value trap) noexcept {-  getPrototypeOf_ = trap;-}--napi_status ProxyHandlerBuilder::GetPrototypeOf(napi_env env,-                                                napi_callback trap,-                                                void* data) noexcept {-  return napi_create_function(-      env, "getPrototypeOf", NAPI_AUTO_LENGTH, trap, data, &getPrototypeOf_);-}--napi_status ProxyHandlerBuilder::GetPrototypeOf(-    napi_env env,-    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return GetPrototypeOf(env, CreateTrapCallback<1>(), &callInfo);-}--napi_value ProxyHandlerBuilder::Has() noexcept {-  return has_;-}--void ProxyHandlerBuilder::Has(napi_value trap) noexcept {-  has_ = trap;-}--napi_status ProxyHandlerBuilder::Has(napi_env env,-                                     napi_callback trap,-                                     void* data) noexcept {-  return napi_create_function(env, "has", NAPI_AUTO_LENGTH, trap, data, &has_);-}--napi_status ProxyHandlerBuilder::Has(napi_env env,-                                     napi_status (*trap)(napi_env env,-                                                         napi_value target,-                                                         napi_value key,-                                                         napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return Has(env, CreateTrapCallback<2>(), &callInfo);-}--napi_status ProxyHandlerBuilder::Has(napi_env env,-                                     napi_status (*trap)(napi_env env,-                                                         napi_value target,-                                                         napi_value key,-                                                         bool* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 bool boolResult{};-                                 CHECK_NAPI(reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], &boolResult));-                                 return napi_get_boolean(-                                     env, boolResult, result);-                               },-                               reinterpret_cast<void*>(trap)};-  return Has(env, CreateTrapCallback<2>(), &callInfo);-}--napi_value ProxyHandlerBuilder::IsExtensible() noexcept {-  return isExtensible_;-}--void ProxyHandlerBuilder::IsExtensible(napi_value trap) noexcept {-  isExtensible_ = trap;-}--napi_status ProxyHandlerBuilder::IsExtensible(napi_env env,-                                              napi_callback trap,-                                              void* data) noexcept {-  return napi_create_function(-      env, "isExtensible", NAPI_AUTO_LENGTH, trap, data, &isExtensible_);-}--napi_status ProxyHandlerBuilder::IsExtensible(-    napi_env env,-    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return IsExtensible(env, CreateTrapCallback<1>(), &callInfo);-}--napi_status ProxyHandlerBuilder::IsExtensible(-    napi_env env,-    napi_status (*trap)(napi_env env, napi_value target, bool* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{-      [](napi_env env,-         void* trap,-         napi_span<napi_value> args,-         napi_value* result) noexcept {-        bool boolResult{};-        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(env, args[0], &boolResult));-        return napi_get_boolean(env, boolResult, result);-      },-      reinterpret_cast<void*>(trap)};-  return IsExtensible(env, CreateTrapCallback<1>(), &callInfo);-}--napi_value ProxyHandlerBuilder::OwnKeys() noexcept {-  return ownKeys_;-}--void ProxyHandlerBuilder::OwnKeys(napi_value trap) noexcept {-  ownKeys_ = trap;-}--napi_status ProxyHandlerBuilder::OwnKeys(napi_env env,-                                         napi_callback trap,-                                         void* data) noexcept {-  return napi_create_function(-      env, "ownKeys", NAPI_AUTO_LENGTH, trap, data, &ownKeys_);-}--napi_status ProxyHandlerBuilder::OwnKeys(-    napi_env env,-    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return OwnKeys(env, CreateTrapCallback<1>(), &callInfo);-}--napi_value ProxyHandlerBuilder::PreventExtensions() noexcept {-  return preventExtensions_;-}--void ProxyHandlerBuilder::PreventExtensions(napi_value trap) noexcept {-  preventExtensions_ = trap;-}--napi_status ProxyHandlerBuilder::PreventExtensions(napi_env env,-                                                   napi_callback trap,-                                                   void* data) noexcept {-  return napi_create_function(env,-                              "preventExtensions",-                              NAPI_AUTO_LENGTH,-                              trap,-                              data,-                              &preventExtensions_);-}--napi_status ProxyHandlerBuilder::PreventExtensions(-    napi_env env,-    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return PreventExtensions(env, CreateTrapCallback<1>(), &callInfo);-}--napi_status ProxyHandlerBuilder::PreventExtensions(-    napi_env env,-    napi_status (*trap)(napi_env env, napi_value target, bool* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{-      [](napi_env env,-         void* trap,-         napi_span<napi_value> args,-         napi_value* result) noexcept {-        bool boolResult{};-        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(env, args[0], &boolResult));-        return napi_get_boolean(env, boolResult, result);-      },-      reinterpret_cast<void*>(trap)};-  return PreventExtensions(env, CreateTrapCallback<1>(), &callInfo);-}--napi_value ProxyHandlerBuilder::Set() noexcept {-  return set_;-}--void ProxyHandlerBuilder::Set(napi_value trap) noexcept {-  set_ = trap;-}--napi_status ProxyHandlerBuilder::Set(napi_env env,-                                     napi_callback trap,-                                     void* data) noexcept {-  return napi_create_function(env, "set", NAPI_AUTO_LENGTH, trap, data, &set_);-}--napi_status ProxyHandlerBuilder::Set(napi_env env,-                                     napi_status (*trap)(napi_env env,-                                                         napi_value target,-                                                         napi_value key,-                                                         napi_value value,-                                                         napi_value receiver,-                                                         napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{-      [](napi_env env,-         void* trap,-         napi_span<napi_value> args,-         napi_value* result) noexcept {-        return reinterpret_cast<TrapType>(trap)(-            env, args[0], args[1], args[2], args[3], result);-      },-      reinterpret_cast<void*>(trap)};-  return Set(env, CreateTrapCallback<4>(), &callInfo);-}--napi_status ProxyHandlerBuilder::Set(napi_env env,-                                     napi_status (*trap)(napi_env env,-                                                         napi_value target,-                                                         napi_value key,-                                                         napi_value value,-                                                         napi_value receiver,-                                                         bool* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{-      [](napi_env env,-         void* trap,-         napi_span<napi_value> args,-         napi_value* result) noexcept {-        bool boolResult{};-        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(-            env, args[0], args[1], args[2], args[3], &boolResult));-        return napi_get_boolean(env, boolResult, result);-      },-      reinterpret_cast<void*>(trap)};-  return Set(env, CreateTrapCallback<4>(), &callInfo);-}--napi_value ProxyHandlerBuilder::SetPrototypeOf() noexcept {-  return setPrototypeOf_;-}--void ProxyHandlerBuilder::SetPrototypeOf(napi_value trap) noexcept {-  setPrototypeOf_ = trap;-}--napi_status ProxyHandlerBuilder::SetPrototypeOf(napi_env env,-                                                napi_callback trap,-                                                void* data) noexcept {-  return napi_create_function(-      env, "setPrototypeOf", NAPI_AUTO_LENGTH, trap, data, &setPrototypeOf_);-}--napi_status ProxyHandlerBuilder::SetPrototypeOf(-    napi_env env,-    napi_status (*trap)(napi_env env,-                        napi_value target,-                        napi_value prototype,-                        napi_value* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 return reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], result);-                               },-                               reinterpret_cast<void*>(trap)};-  return SetPrototypeOf(env, CreateTrapCallback<2>(), &callInfo);-}--napi_status ProxyHandlerBuilder::SetPrototypeOf(-    napi_env env,-    napi_status (*trap)(-        napi_env env, napi_value target, napi_value prototype, bool* result)) {-  using TrapType = decltype(trap);-  static TrapCallInfo callInfo{[](napi_env env,-                                  void* trap,-                                  napi_span<napi_value> args,-                                  napi_value* result) noexcept {-                                 bool boolResult{};-                                 CHECK_NAPI(reinterpret_cast<TrapType>(trap)(-                                     env, args[0], args[1], &boolResult));-                                 return napi_get_boolean(-                                     env, boolResult, result);-                               },-                               reinterpret_cast<void*>(trap)};-  return SetPrototypeOf(env, CreateTrapCallback<2>(), &callInfo);-}--//=============--ProxyTemplate::ProxyTemplate(napi_env env, napi_value proxyHandler) noexcept-    : proxyHandler_(RefHolder(env, proxyHandler)) {}--napi_status ProxyTemplate::NewInstance(napi_env env,-                                       napi_value target,-                                       napi_value* result) noexcept {-  napi_value proxyConstructor{};-  CHECK_NAPI(GetProxyConstructor(env, &proxyConstructor));--  napi_value args[] = {target, static_cast<napi_value>(proxyHandler_)};-  return napi_new_instance(env, proxyConstructor, 2, args, result);-}--napi_status ProxyTemplate::GetProxyConstructor(napi_env env,-                                               napi_value* result) noexcept {-  if (!proxyConstructor_) {-    napi_value global{}, proxyConstructor{};-    CHECK_NAPI(napi_get_global(env, &global));-    CHECK_NAPI(-        napi_get_named_property(env, global, "Proxy", &proxyConstructor));-    proxyConstructor_ = RefHolder(env, proxyConstructor);-  }-  *result = proxyConstructor_;-  return napi_ok;-}

object-template-demo/napi/proxy-template.h

deleted file mode 100644@@ -1,249 +0,0 @@-#include "node-api-common.h"--template <typename T>-using napi_span = span<T>;--// Creates a handler object for a JavaScript Proxy.-// See-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy-// for details about JavaScript Proxy.-//-// There are four different ways we can set each Proxy handler trap:-// - using napi_value function.-// - using napi_callback that creates function.-// - using a callback signature that matches Proxy handler definition arguments.-// - using a callback based on the Proxy handler trap signature where we replace-//   napi_value with strongly typed values such as bool or-//   napi_span<napi_value>.-//-// Note that ProxyHandlerBuilder keeps handler trap functions as napi_value-// and thus cannot be persisted. The typical usage is to create new-// ProxyHandlerBuilder instance on the call stack, set handler traps, create-// handler to pass to Proxy constructor or ProxyTemplate, and not to reuse the-// ProxyHandlerBuilder instance.-struct ProxyHandlerBuilder {-  napi_status NewHandler(napi_env env, napi_value* result) noexcept;--  napi_value Apply() noexcept;-  void Apply(napi_value trap) noexcept;-  napi_status Apply(napi_env env,-                    napi_callback trap,-                    void* data = nullptr) noexcept;-  napi_status Apply(napi_env env,-                    napi_status (*trap)(napi_env env,-                                        napi_value target,-                                        napi_value thisArg,-                                        napi_value argumentList,-                                        napi_value* result));-  napi_status Apply(napi_env env,-                    napi_status (*trap)(napi_env env,-                                        napi_value target,-                                        napi_value thisArg,-                                        napi_span<napi_value> argumentList,-                                        napi_value* result));--  napi_value Construct() noexcept;-  void Construct(napi_value trap) noexcept;-  napi_status Construct(napi_env env,-                        napi_callback trap,-                        void* data = nullptr) noexcept;-  napi_status Construct(napi_env env,-                        napi_status (*trap)(napi_env env,-                                            napi_value target,-                                            napi_value argumentList,-                                            napi_value newTarget,-                                            napi_value* result));-  napi_status Construct(napi_env env,-                        napi_status (*trap)(napi_env env,-                                            napi_value target,-                                            napi_span<napi_value> argumentList,-                                            napi_value newTarget,-                                            napi_value* result));--  napi_value DefineProperty() noexcept;-  void DefineProperty(napi_value trap) noexcept;-  napi_status DefineProperty(napi_env env,-                             napi_callback trap,-                             void* data = nullptr) noexcept;-  napi_status DefineProperty(napi_env env,-                             napi_status (*trap)(napi_env env,-                                                 napi_value target,-                                                 napi_value key,-                                                 napi_value descriptor,-                                                 napi_value* result));-  napi_status DefineProperty(napi_env env,-                             napi_status (*trap)(napi_env env,-                                                 napi_value target,-                                                 napi_value key,-                                                 napi_value descriptor,-                                                 bool* result));--  napi_value DeleteProperty() noexcept;-  void DeleteProperty(napi_value trap) noexcept;-  napi_status DeleteProperty(napi_env env,-                             napi_callback trap,-                             void* data = nullptr) noexcept;-  napi_status DeleteProperty(napi_env env,-                             napi_status (*trap)(napi_env env,-                                                 napi_value target,-                                                 napi_value key,-                                                 napi_value* result));-  napi_status DeleteProperty(napi_env env,-                             napi_status (*trap)(napi_env env,-                                                 napi_value target,-                                                 napi_value key,-                                                 bool* result));--  napi_value Get() noexcept;-  void Get(napi_value trap) noexcept;-  napi_status Get(napi_env env,-                  napi_callback trap,-                  void* data = nullptr) noexcept;-  napi_status Get(napi_env env,-                  napi_status (*trap)(napi_env env,-                                      napi_value target,-                                      napi_value key,-                                      napi_value receiver,-                                      napi_value* result));--  napi_value GetOwnPropertyDescriptor() noexcept;-  void GetOwnPropertyDescriptor(napi_value trap) noexcept;-  napi_status GetOwnPropertyDescriptor(napi_env env,-                                       napi_callback trap,-                                       void* data = nullptr) noexcept;-  napi_status GetOwnPropertyDescriptor(napi_env env,-                                       napi_status (*trap)(napi_env env,-                                                           napi_value target,-                                                           napi_value key,-                                                           napi_value* result));--  napi_value GetPrototypeOf() noexcept;-  void GetPrototypeOf(napi_value trap) noexcept;-  napi_status GetPrototypeOf(napi_env env,-                             napi_callback trap,-                             void* data = nullptr) noexcept;-  napi_status GetPrototypeOf(napi_env env,-                             napi_status (*trap)(napi_env env,-                                                 napi_value target,-                                                 napi_value* result));--  napi_value Has() noexcept;-  void Has(napi_value trap) noexcept;-  napi_status Has(napi_env env,-                  napi_callback trap,-                  void* data = nullptr) noexcept;-  napi_status Has(napi_env env,-                  napi_status (*trap)(napi_env env,-                                      napi_value target,-                                      napi_value key,-                                      napi_value* result));-  napi_status Has(napi_env env,-                  napi_status (*trap)(napi_env env,-                                      napi_value target,-                                      napi_value key,-                                      bool* result));--  napi_value IsExtensible() noexcept;-  void IsExtensible(napi_value trap) noexcept;-  napi_status IsExtensible(napi_env env,-                           napi_callback trap,-                           void* data = nullptr) noexcept;-  napi_status IsExtensible(napi_env env,-                           napi_status (*trap)(napi_env env,-                                               napi_value target,-                                               napi_value* result));-  napi_status IsExtensible(napi_env env,-                           napi_status (*trap)(napi_env env,-                                               napi_value target,-                                               bool* result));--  napi_value OwnKeys() noexcept;-  void OwnKeys(napi_value trap) noexcept;-  napi_status OwnKeys(napi_env env,-                      napi_callback trap,-                      void* data = nullptr) noexcept;-  napi_status OwnKeys(napi_env env,-                      napi_status (*trap)(napi_env env,-                                          napi_value target,-                                          napi_value* result));--  napi_value PreventExtensions() noexcept;-  void PreventExtensions(napi_value trap) noexcept;-  napi_status PreventExtensions(napi_env env,-                                napi_callback trap,-                                void* data = nullptr) noexcept;-  napi_status PreventExtensions(napi_env env,-                                napi_status (*trap)(napi_env env,-                                                    napi_value target,-                                                    napi_value* result));-  napi_status PreventExtensions(napi_env env,-                                napi_status (*trap)(napi_env env,-                                                    napi_value target,-                                                    bool* result));--  napi_value Set() noexcept;-  void Set(napi_value trap) noexcept;-  napi_status Set(napi_env env,-                  napi_callback trap,-                  void* data = nullptr) noexcept;-  napi_status Set(napi_env env,-                  napi_status (*trap)(napi_env env,-                                      napi_value target,-                                      napi_value key,-                                      napi_value value,-                                      napi_value receiver,-                                      napi_value* result));-  napi_status Set(napi_env env,-                  napi_status (*trap)(napi_env env,-                                      napi_value target,-                                      napi_value key,-                                      napi_value value,-                                      napi_value receiver,-                                      bool* result));--  napi_value SetPrototypeOf() noexcept;-  void SetPrototypeOf(napi_value trap) noexcept;-  napi_status SetPrototypeOf(napi_env env,-                             napi_callback trap,-                             void* data = nullptr) noexcept;-  napi_status SetPrototypeOf(napi_env env,-                             napi_status (*trap)(napi_env env,-                                                 napi_value target,-                                                 napi_value prototype,-                                                 napi_value* result));-  napi_status SetPrototypeOf(napi_env env,-                             napi_status (*trap)(napi_env env,-                                                 napi_value target,-                                                 napi_value prototype,-                                                 bool* result));-- private:-  napi_value apply_{};-  napi_value construct_{};-  napi_value defineProperty_{};-  napi_value deleteProperty_{};-  napi_value get_{};-  napi_value getOwnPropertyDescriptor_{};-  napi_value getPrototypeOf_{};-  napi_value has_{};-  napi_value isExtensible_{};-  napi_value ownKeys_{};-  napi_value preventExtensions_{};-  napi_value set_{};-  napi_value setPrototypeOf_{};-};--struct ProxyTemplate {-  ProxyTemplate(napi_env env, napi_value proxyHandler) noexcept;--  napi_status NewInstance(napi_env env,-                          napi_value target,-                          napi_value* result) noexcept;-- private:-  napi_status GetProxyConstructor(napi_env env, napi_value* result) noexcept;-- private:-  RefHolder proxyConstructor_{};-  RefHolder proxyHandler_{};-};

object-wrap-demo/node-addon-api/README.md

deleted file mode 100644@@ -1,14 +0,0 @@-# Node-API Object Wrap Demo--This is an example project that accompanies the Node-API workshop tutorials--A tutorial describing this project can be found at the [Node-API Resource](https://napi.inspiredware.com/getting-started/objectwrap.html).--To build and run this program on your system, clone it to your computer and run these two commands inside your clone:--```-npm install-npm test-```--> You need to have Node 10.5.0 or later installed. \ No newline at end of file

object-wrap-demo/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,20 +0,0 @@-{-  'targets': [-    {-      'target_name': 'object-wrap-demo-native',-      'sources': [ 'src/object_wrap_demo.cc' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'xcode_settings': {-        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-        'CLANG_CXX_LIBRARY': 'libc++',-        'MACOSX_DEPLOYMENT_TARGET': '10.7'-      },-      'msvs_settings': {-        'VCCLCompilerTool': { 'ExceptionHandling': 1 },-      }-    }-  ]-}\ No newline at end of file

object-wrap-demo/node-addon-api/lib/binding.js

deleted file mode 100644@@ -1,11 +0,0 @@-const addon = require('../build/Release/object-wrap-demo-native');--function ObjectWrapDemo(name) {-    this.greet = function(str) {-        return _addonInstance.greet(str);-    }--    var _addonInstance = new addon.ObjectWrapDemo(name);-}--module.exports = ObjectWrapDemo;

object-wrap-demo/node-addon-api/package.json

deleted file mode 100644@@ -1,16 +0,0 @@-{-  "main": "lib/binding.js",-  "private": true,-  "dependencies": {-    "node-addon-api": "^1.1.0"-  },-  "scripts": {-    "test": "node --napi-modules ./test/test_binding.js"-  },-  "gypfile": true,-  "name": "object-wrap-demo",-  "version": "1.0.0",-  "description": "An object wrapper demo",-  "author": "Your name goes here",-  "license": "MIT"-}

object-wrap-demo/node-addon-api/src/object_wrap_demo.cc

deleted file mode 100644@@ -1,62 +0,0 @@-#include "object_wrap_demo.h"--using namespace Napi;--ObjectWrapDemo::ObjectWrapDemo(const Napi::CallbackInfo& info)-    : ObjectWrap(info) {-  Napi::Env env = info.Env();--  if (info.Length() < 1) {-    Napi::TypeError::New(env, "Wrong number of arguments")-        .ThrowAsJavaScriptException();-    return;-  }--  if (!info[0].IsString()) {-    Napi::TypeError::New(env, "You need to name yourself")-        .ThrowAsJavaScriptException();-    return;-  }--  this->_greeterName = info[0].As<Napi::String>().Utf8Value();-}--Napi::Value ObjectWrapDemo::Greet(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();--  if (info.Length() < 1) {-    Napi::TypeError::New(env, "Wrong number of arguments")-        .ThrowAsJavaScriptException();-    return env.Null();-  }--  if (!info[0].IsString()) {-    Napi::TypeError::New(env, "You need to introduce yourself to greet")-        .ThrowAsJavaScriptException();-    return env.Null();-  }--  Napi::String name = info[0].As<Napi::String>();--  printf("Hello %s\n", name.Utf8Value().c_str());-  printf("I am %s\n", this->_greeterName.c_str());--  return Napi::String::New(env, this->_greeterName);-}--Napi::Function ObjectWrapDemo::GetClass(Napi::Env env) {-  return DefineClass(-      env,-      "ObjectWrapDemo",-      {-          ObjectWrapDemo::InstanceMethod("greet", &ObjectWrapDemo::Greet),-      });-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  Napi::String name = Napi::String::New(env, "ObjectWrapDemo");-  exports.Set(name, ObjectWrapDemo::GetClass(env));-  return exports;-}--NODE_API_MODULE(addon, Init)

object-wrap-demo/node-addon-api/src/object_wrap_demo.h

deleted file mode 100644@@ -1,14 +0,0 @@-#pragma once--#include <napi.h>--class ObjectWrapDemo : public Napi::ObjectWrap<ObjectWrapDemo> {- public:-  ObjectWrapDemo(const Napi::CallbackInfo&);-  Napi::Value Greet(const Napi::CallbackInfo&);--  static Napi::Function GetClass(Napi::Env);-- private:-  std::string _greeterName;-};

object-wrap-demo/node-addon-api/test/test_binding.js

deleted file mode 100644@@ -1,21 +0,0 @@-const ObjectWrapDemo = require("../lib/binding.js");-const assert = require("assert");--assert(ObjectWrapDemo, "The expected module is undefined");--function testBasic()-{-    const instance = new ObjectWrapDemo("mr-yeoman");-    assert(instance.greet, "The expected method is not defined");-    assert.strictEqual(instance.greet("kermit"), "mr-yeoman", "Unexpected value returned");-}--function testInvalidParams()-{-    const instance = new ObjectWrapDemo();-}--assert.doesNotThrow(testBasic, undefined, "testBasic threw an expection");-assert.throws(testInvalidParams, undefined, "testInvalidParams didn't throw");--console.log("Tests passed- everything looks OK!");\ No newline at end of file

promise-callback-demo/node-addon-api/README.md

deleted file mode 100644@@ -1,7 +0,0 @@-# Node-API Promise Callback Demo--To build and run this program on your system, clone it to your computer and run these two commands inside your clone:--```-npm install-```

promise-callback-demo/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,20 +0,0 @@-{-  'targets': [-    {-      'target_name': 'promise-callback-demo',-      'sources': [ 'src/promise_callback_demo.cc' ],-      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-      'cflags!': [ '-fno-exceptions' ],-      'cflags_cc!': [ '-fno-exceptions' ],-      'xcode_settings': {-        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-        'CLANG_CXX_LIBRARY': 'libc++',-        'MACOSX_DEPLOYMENT_TARGET': '10.7'-      },-      'msvs_settings': {-        'VCCLCompilerTool': { 'ExceptionHandling': 1 },-      }-    }-  ]-}

promise-callback-demo/node-addon-api/package.json

deleted file mode 100644@@ -1,18 +0,0 @@-{-  "name": "promise-callback-demo",-  "main": "test/index.js",-  "private": true,-  "dependencies": {-    "node-addon-api": "^4.0.0"-  },-  "scripts": {-    "install": "node-gyp rebuild && node test"-  },-  "engines": {-    "node": ">= 10.16.0"-  },-  "version": "1.0.0",-  "description": "An promise callback demo",-  "author": "Node-API Team",-  "license": "ISC"-}

promise-callback-demo/node-addon-api/src/promise_callback_demo.cc

deleted file mode 100644@@ -1,121 +0,0 @@-#include <napi.h>-#include <future>-#include <iostream>-#include <thread>--using namespace Napi;--class PromiseCallbackDemo;-using Context = PromiseCallbackDemo;-using DataType = std::promise<std::string>;-void CallJs(Napi::Env env, Function callback, Context* context, DataType* data);-using TSFN = TypedThreadSafeFunction<Context, DataType, CallJs>;-using FinalizerDataType = void;--class PromiseCallbackDemo : public Napi::ObjectWrap<PromiseCallbackDemo> {- public:-  PromiseCallbackDemo(const Napi::CallbackInfo&);--  static Napi::Function GetClass(Napi::Env);--  std::thread native_thread;-  TSFN tsfn;-};--void thread_entry(PromiseCallbackDemo* obj) {-  for (auto i = 0; i < 10; ++i) {-    std::promise<std::string> promise;-    auto future = promise.get_future();-    obj->tsfn.NonBlockingCall(&promise);--    // With exceptions disabled, STL calls will abort the thread, since we-    // cannot try/catch, as the calls to `std::make_exception_ptr()` will abort.-    try {-      auto result = future.get();-      std::cout << "Result from JS, call " << i << ": " << result << "\n";-    } catch (const std::exception& e) {-      std::cout << "Error from JS, call " << i << ": " << e.what() << "\n";-    }-  }-  obj->tsfn.Release();-}--void CallJs(Napi::Env env,-            Function callback,-            Context* context,-            DataType* data) {-  // Is the JavaScript environment still available to call into, eg. the TSFN is-  // not aborted-  if (env != nullptr) {-    auto jsPromise = callback.Call({}).As<Napi::Object>();-    auto then = jsPromise.Get("then").As<Function>();-    // Attach the resolve handler.-    // TODO proper error handling (add failure handler)-    then.Call(jsPromise,-              {Napi::Function::New(env,-                                   [=](const CallbackInfo& info) {-                                     auto result =-                                         info[0].As<String>().Utf8Value();-                                     data->set_value(result);-                                   }),-               Napi::Function::New(env, [=](const CallbackInfo& info) {-                 auto result = info[0].As<String>().Utf8Value();-                 data->set_exception(std::make_exception_ptr(-                     std::runtime_error("Error in jsCallback")));-               })});--  } else {-    data->set_exception(std::make_exception_ptr(-        std::runtime_error("Environment is shut down")));-  }-}--PromiseCallbackDemo::PromiseCallbackDemo(const Napi::CallbackInfo& info)-    : ObjectWrap(info) {-  Napi::Env env = info.Env();--  // Argument checking-  if (info.Length() < 1) {-    Napi::TypeError::New(env, "Wrong number of arguments")-        .ThrowAsJavaScriptException();-    return;-  }--  if (!info[0].IsFunction()) {-    Napi::TypeError::New(env, "First argument must be a function")-        .ThrowAsJavaScriptException();-    return;-  }--  // Since we are storing the std::thread on this ObjectWrap instance, we should-  // reference it so it doesn't get garbage collected, and unreference it on-  // TSFN finalize.-  Ref();--  tsfn = TSFN::New(-      env,-      info[0].As<Function>(),  // JavaScript function called asynchronously-      "PromiseCallbackDemo",   // Name-      0,                       // Unlimited queue-      1,                       // Only one thread will use this initially-      this,                    // Context-      [](Napi::Env,-         FinalizerDataType*,-         Context* ctx) {  // Finalizer used to clean threads up-        ctx->Unref();-        ctx->native_thread.join();-      });--  native_thread = std::thread(thread_entry, this);-}--Napi::Function PromiseCallbackDemo::GetClass(Napi::Env env) {-  return DefineClass(env, "PromiseCallbackDemo", {});-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports["PromiseCallbackDemo"] = PromiseCallbackDemo::GetClass(env);-  return exports;-}--NODE_API_MODULE(addon, Init)

promise-callback-demo/node-addon-api/test/index.js

deleted file mode 100644@@ -1,11 +0,0 @@-const { PromiseCallbackDemo } = require('../build/Release/promise-callback-demo');--let shouldFail = false;-// Resolve or reject a promise with an ISO date format after 100 milliseconds-function jsCallback() {-    return new Promise((resolve, reject) => setTimeout(() => {-        ((shouldFail = !shouldFail) ? reject : resolve)(new Date().toISOString());-    }, 100));-}--new PromiseCallbackDemo(jsCallback);

src/1-getting-started/1_hello_world/README.md

new file mode 100644@@ -0,0 +1,8 @@+## Example 1: *Hello world*++To get started let's make a small addon which is the C++ equivalent of+the following JavaScript code:++```js+module.exports.hello = function() { return 'world'; };+```

src/1-getting-started/1_hello_world/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "hello",+      "sources": [ "hello.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/1-getting-started/1_hello_world/nan/hello.cc

new file mode 100644@@ -0,0 +1,17 @@+#include <nan.h>++void Method(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  info.GetReturnValue().Set(Nan::New("world").ToLocalChecked());+}++void Init(v8::Local<v8::Object> exports) {+  v8::Local<v8::Context> context =+      exports->GetCreationContext().ToLocalChecked();+  exports->Set(context,+               Nan::New("hello").ToLocalChecked(),+               Nan::New<v8::FunctionTemplate>(Method)+                   ->GetFunction(context)+                   .ToLocalChecked());+}++NODE_MODULE(hello, Init)

src/1-getting-started/1_hello_world/nan/hello.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('hello');++console.log(addon.hello()); // 'world'\ No newline at end of file

src/1-getting-started/1_hello_world/nan/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "hello_world",+  "version": "0.0.0",+  "description": "Node.js Addons Example #1",+  "main": "hello.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "nan": "^2.0.0"+  },+  "scripts": {+    "test": "node hello.js"+  },+  "gypfile": true+}

src/1-getting-started/1_hello_world/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "hello",+      "sources": [ "hello.c" ]+    }+  ]+}

src/1-getting-started/1_hello_world/napi/hello.c

new file mode 100644@@ -0,0 +1,23 @@+#include <assert.h>+#include <node_api.h>++static napi_value Method(napi_env env, napi_callback_info info) {+  napi_status status;+  napi_value world;+  status = napi_create_string_utf8(env, "world", 5, &world);+  assert(status == napi_ok);+  return world;+}++#define DECLARE_NAPI_METHOD(name, func)                                        \+  { name, 0, func, 0, 0, 0, napi_default, 0 }++static napi_value Init(napi_env env, napi_value exports) {+  napi_status status;+  napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);+  status = napi_define_properties(env, exports, 1, &desc);+  assert(status == napi_ok);+  return exports;+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/1-getting-started/1_hello_world/napi/hello.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('hello');++console.log(addon.hello()); // 'world'

src/1-getting-started/1_hello_world/napi/package.json

new file mode 100644@@ -0,0 +1,14 @@+{+  "name": "hello_world",+  "version": "0.0.0",+  "description": "Node.js Addons Example #1",+  "main": "hello.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1"+  },+  "scripts": {+    "test": "node hello.js"+  },+  "gypfile": true+}

src/1-getting-started/1_hello_world/node-addon-api-addon-class/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "hello",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "hello.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': ['NAPI_DISABLE_CPP_EXCEPTIONS'],+    }+  ]+}

src/1-getting-started/1_hello_world/node-addon-api-addon-class/hello.cc

new file mode 100644@@ -0,0 +1,16 @@+#include <napi.h>++class HelloAddon : public Napi::Addon<HelloAddon> {+ public:+  HelloAddon(Napi::Env env, Napi::Object exports) {+    DefineAddon(exports,+                {InstanceMethod("hello", &HelloAddon::Hello, napi_enumerable)});+  }++ private:+  Napi::Value Hello(const Napi::CallbackInfo& info) {+    return Napi::String::New(info.Env(), "world");+  }+};++NODE_API_ADDON(HelloAddon)

src/1-getting-started/1_hello_world/node-addon-api-addon-class/hello.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('hello');++console.log(addon.hello()); // 'world'

src/1-getting-started/1_hello_world/node-addon-api-addon-class/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "hello_world",+  "version": "0.0.0",+  "description": "Node.js Addons Example #1",+  "main": "hello.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "node-addon-api": "^7.0.0"+  },+  "scripts": {+    "test": "node hello.js"+  },+  "gypfile": true+}

src/1-getting-started/1_hello_world/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "hello",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "hello.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/1-getting-started/1_hello_world/node-addon-api/hello.cc

new file mode 100644@@ -0,0 +1,14 @@+#include <napi.h>++Napi::String Method(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  return Napi::String::New(env, "world");+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "hello"),+              Napi::Function::New(env, Method));+  return exports;+}++NODE_API_MODULE(hello, Init)

src/1-getting-started/1_hello_world/node-addon-api/hello.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('hello');++console.log(addon.hello()); // 'world'

src/1-getting-started/1_hello_world/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "hello_world",+  "version": "0.0.0",+  "description": "Node.js Addons Example #1",+  "main": "hello.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "node-addon-api": "^1.0.0"+  },+  "scripts": {+    "test": "node hello.js"+  },+  "gypfile": true+}

src/1-getting-started/2_function_arguments/README.md

new file mode 100644@@ -0,0 +1,2 @@+## Example 2: *Function arguments*+

src/1-getting-started/2_function_arguments/nan/addon.cc

new file mode 100644@@ -0,0 +1,33 @@+#include <nan.h>++void Add(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();++  if (info.Length() < 2) {+    Nan::ThrowTypeError("Wrong number of arguments");+    return;+  }++  if (!info[0]->IsNumber() || !info[1]->IsNumber()) {+    Nan::ThrowTypeError("Wrong arguments");+    return;+  }++  double arg0 = info[0]->NumberValue(context).FromJust();+  double arg1 = info[1]->NumberValue(context).FromJust();+  v8::Local<v8::Number> num = Nan::New(arg0 + arg1);++  info.GetReturnValue().Set(num);+}++void Init(v8::Local<v8::Object> exports) {+  v8::Local<v8::Context> context =+      exports->GetCreationContext().ToLocalChecked();+  exports->Set(context,+               Nan::New("add").ToLocalChecked(),+               Nan::New<v8::FunctionTemplate>(Add)+                   ->GetFunction(context)+                   .ToLocalChecked());+}++NODE_MODULE(addon, Init)

src/1-getting-started/2_function_arguments/nan/addon.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('addon.node')++console.log('This should be eight:', addon.add(3, 5))\ No newline at end of file

src/1-getting-started/2_function_arguments/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/1-getting-started/2_function_arguments/nan/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "function_arguments",+  "version": "0.0.0",+  "description": "Node.js Addons Example #2",+  "main": "addon.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "nan": "^2.0.0"+  },+  "scripts": {+    "test": "node addon.js"+  },+  "gypfile": true+}

src/1-getting-started/2_function_arguments/napi/addon.c

new file mode 100644@@ -0,0 +1,56 @@+#include <assert.h>+#include <node_api.h>+#include <stdio.h>+static napi_value Add(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 2;+  napi_value args[2];+  status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);+  assert(status == napi_ok);++  if (argc < 2) {+    napi_throw_type_error(env, NULL, "Wrong number of arguments");+    return NULL;+  }++  napi_valuetype valuetype0;+  status = napi_typeof(env, args[0], &valuetype0);+  assert(status == napi_ok);++  napi_valuetype valuetype1;+  status = napi_typeof(env, args[1], &valuetype1);+  assert(status == napi_ok);++  if (valuetype0 != napi_number || valuetype1 != napi_number) {+    napi_throw_type_error(env, NULL, "Wrong arguments");+    return NULL;+  }++  double value0;+  status = napi_get_value_double(env, args[0], &value0);+  assert(status == napi_ok);++  double value1;+  status = napi_get_value_double(env, args[1], &value1);+  assert(status == napi_ok);++  napi_value sum;+  status = napi_create_double(env, value0 + value1, &sum);+  assert(status == napi_ok);++  return sum;+}++#define DECLARE_NAPI_METHOD(name, func)                                        \+  { name, 0, func, 0, 0, 0, napi_default, 0 }++napi_value Init(napi_env env, napi_value exports) {+  napi_status status;+  napi_property_descriptor addDescriptor = DECLARE_NAPI_METHOD("add", Add);+  status = napi_define_properties(env, exports, 1, &addDescriptor);+  assert(status == napi_ok);+  return exports;+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/1-getting-started/2_function_arguments/napi/addon.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('addon.node')++console.log('This should be eight:', addon.add(3, 5))\ No newline at end of file

src/1-getting-started/2_function_arguments/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.c" ]+    }+  ]+}

src/1-getting-started/2_function_arguments/napi/package.json

new file mode 100644@@ -0,0 +1,14 @@+{+  "name": "function_arguments",+  "version": "0.0.0",+  "description": "Node.js Addons Example #2",+  "main": "addon.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1"+  },+  "scripts": {+    "test": "node addon.js"+  },+  "gypfile": true+}

src/1-getting-started/2_function_arguments/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,29 @@+#include <napi.h>++Napi::Value Add(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();++  if (info.Length() < 2) {+    Napi::TypeError::New(env, "Wrong number of arguments")+        .ThrowAsJavaScriptException();+    return env.Null();+  }++  if (!info[0].IsNumber() || !info[1].IsNumber()) {+    Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();+    return env.Null();+  }++  double arg0 = info[0].As<Napi::Number>().DoubleValue();+  double arg1 = info[1].As<Napi::Number>().DoubleValue();+  Napi::Number num = Napi::Number::New(env, arg0 + arg1);++  return num;+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "add"), Napi::Function::New(env, Add));+  return exports;+}++NODE_API_MODULE(addon, Init)

src/1-getting-started/2_function_arguments/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('addon.node')++console.log('This should be eight:', addon.add(3, 5))

src/1-getting-started/2_function_arguments/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "addon",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/1-getting-started/2_function_arguments/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "function_arguments",+  "version": "0.0.0",+  "description": "Node.js Addons Example #2",+  "main": "addon.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "node-addon-api": "^1.0.0"+  },+  "scripts": {+    "test": "node addon.js"+  },+  "gypfile": true+}

src/1-getting-started/3_callbacks/nan/addon.cc

new file mode 100644@@ -0,0 +1,15 @@+#include <nan.h>++void RunCallback(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Function> cb = info[0].As<v8::Function>();+  const unsigned argc = 1;+  v8::Local<v8::Value> argv[argc] = {Nan::New("hello world").ToLocalChecked()};+  Nan::AsyncResource resource("nan:makeCallback");+  resource.runInAsyncScope(Nan::GetCurrentContext()->Global(), cb, argc, argv);+}++void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {+  Nan::SetMethod(module, "exports", RunCallback);+}++NODE_MODULE(addon, Init)

src/1-getting-started/3_callbacks/nan/addon.js

new file mode 100644@@ -0,0 +1,5 @@+var addon = require('bindings')('addon');++addon(function(msg){+  console.log(msg); // 'hello world'+});\ No newline at end of file

src/1-getting-started/3_callbacks/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/1-getting-started/3_callbacks/nan/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "callbacks",+  "version": "0.0.0",+  "description": "Node.js Addons Example #3",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "nan": "^2.14.0"+  }+}

src/1-getting-started/3_callbacks/napi/addon.c

new file mode 100644@@ -0,0 +1,37 @@+#include <assert.h>+#include <node_api.h>++static napi_value RunCallback(napi_env env, const napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value args[1];+  status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);+  assert(status == napi_ok);++  napi_value cb = args[0];++  napi_value argv[1];+  status = napi_create_string_utf8(env, "hello world", NAPI_AUTO_LENGTH, argv);+  assert(status == napi_ok);++  napi_value global;+  status = napi_get_global(env, &global);+  assert(status == napi_ok);++  napi_value result;+  status = napi_call_function(env, global, cb, 1, argv, &result);+  assert(status == napi_ok);++  return NULL;+}++static napi_value Init(napi_env env, napi_value exports) {+  napi_value new_exports;+  napi_status status = napi_create_function(+      env, "", NAPI_AUTO_LENGTH, RunCallback, NULL, &new_exports);+  assert(status == napi_ok);+  return new_exports;+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/1-getting-started/3_callbacks/napi/addon.js

new file mode 100644@@ -0,0 +1,5 @@+var addon = require('bindings')('addon');++addon(function(msg){+  console.log(msg); // 'hello world'+});

src/1-getting-started/3_callbacks/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.c" ]+    }+  ]+}

src/1-getting-started/3_callbacks/napi/package.json

new file mode 100644@@ -0,0 +1,11 @@+{+  "name": "napi_callbacks",+  "version": "0.0.0",+  "description": "Node.js Addons Example #3",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.2.1"+  }+}

src/1-getting-started/3_callbacks/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,13 @@+#include <napi.h>++void RunCallback(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  Napi::Function cb = info[0].As<Napi::Function>();+  cb.Call(env.Global(), {Napi::String::New(env, "hello world")});+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  return Napi::Function::New(env, RunCallback);+}++NODE_API_MODULE(addon, Init)

src/1-getting-started/3_callbacks/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,5 @@+var addon = require('bindings')('addon');++addon(function(msg){+  console.log(msg); // 'hello world'+});

src/1-getting-started/3_callbacks/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "addon",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/1-getting-started/3_callbacks/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "callbacks",+  "version": "0.0.0",+  "description": "Node.js Addons Example #3",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "node-addon-api": "^1.0.0"+  }+}

src/1-getting-started/4_object_factory/nan/addon.cc

new file mode 100644@@ -0,0 +1,23 @@+#include <nan.h>++void CreateObject(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();+  v8::Local<v8::Object> obj = Nan::New<v8::Object>();+  obj->Set(context,+           Nan::New("msg").ToLocalChecked(),+           info[0]->ToString(context).ToLocalChecked());++  info.GetReturnValue().Set(obj);+}++void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {+  v8::Local<v8::Context> context =+      exports->GetCreationContext().ToLocalChecked();+  module->Set(context,+              Nan::New("exports").ToLocalChecked(),+              Nan::New<v8::FunctionTemplate>(CreateObject)+                  ->GetFunction(context)+                  .ToLocalChecked());+}++NODE_MODULE(addon, Init)

src/1-getting-started/4_object_factory/nan/addon.js

new file mode 100644@@ -0,0 +1,5 @@+var addon = require('bindings')('addon');++var obj1 = addon('hello');+var obj2 = addon('world');+console.log(obj1.msg+' '+obj2.msg); // 'hello world'\ No newline at end of file

src/1-getting-started/4_object_factory/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/1-getting-started/4_object_factory/nan/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "object_factory",+  "version": "0.0.0",+  "description": "Node.js Addons Example #4",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "nan": "^2.14.0"+  }+}

src/1-getting-started/4_object_factory/napi/addon.c

new file mode 100644@@ -0,0 +1,30 @@+#include <assert.h>+#include <node_api.h>++static napi_value CreateObject(napi_env env, const napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value args[1];+  status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);+  assert(status == napi_ok);++  napi_value obj;+  status = napi_create_object(env, &obj);+  assert(status == napi_ok);++  status = napi_set_named_property(env, obj, "msg", args[0]);+  assert(status == napi_ok);++  return obj;+}++static napi_value Init(napi_env env, napi_value exports) {+  napi_value new_exports;+  napi_status status = napi_create_function(+      env, "", NAPI_AUTO_LENGTH, CreateObject, NULL, &new_exports);+  assert(status == napi_ok);+  return new_exports;+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/1-getting-started/4_object_factory/napi/addon.js

new file mode 100644@@ -0,0 +1,5 @@+var addon = require('bindings')('addon');++var obj1 = addon('hello');+var obj2 = addon('world');+console.log(obj1.msg+' '+obj2.msg); // 'hello world'

src/1-getting-started/4_object_factory/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.c" ]+    }+  ]+}

src/1-getting-started/4_object_factory/napi/package.json

new file mode 100644@@ -0,0 +1,11 @@+{+  "name": "object_factory",+  "version": "0.0.0",+  "description": "Node.js Addons Example #4",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.2.1"+  }+}

src/1-getting-started/4_object_factory/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,15 @@+#include <napi.h>++Napi::Object CreateObject(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  Napi::Object obj = Napi::Object::New(env);+  obj.Set(Napi::String::New(env, "msg"), info[0].ToString());++  return obj;+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  return Napi::Function::New(env, CreateObject, "createObject");+}++NODE_API_MODULE(addon, Init)

src/1-getting-started/4_object_factory/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,5 @@+var addon = require('bindings')('addon');++var obj1 = addon('hello');+var obj2 = addon('world');+console.log(obj1.msg+' '+obj2.msg); // 'hello world'\ No newline at end of file

src/1-getting-started/4_object_factory/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "addon",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/1-getting-started/4_object_factory/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "object_factory",+  "version": "0.0.0",+  "description": "Node.js Addons Example #4",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "node-addon-api": "^1.0.0"+  }+}

src/1-getting-started/5_function_factory/nan/addon.cc

new file mode 100644@@ -0,0 +1,23 @@+#include <nan.h>++void MyFunction(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  info.GetReturnValue().Set(Nan::New("hello world").ToLocalChecked());+}++void CreateFunction(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();+  v8::Local<v8::FunctionTemplate> tpl =+      Nan::New<v8::FunctionTemplate>(MyFunction);+  v8::Local<v8::Function> fn = tpl->GetFunction(context).ToLocalChecked();++  // omit this to make it anonymous+  fn->SetName(Nan::New("theFunction").ToLocalChecked());++  info.GetReturnValue().Set(fn);+}++void Init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {+  Nan::SetMethod(module, "exports", CreateFunction);+}++NODE_MODULE(addon, Init)

src/1-getting-started/5_function_factory/nan/addon.js

new file mode 100644@@ -0,0 +1,4 @@+var addon = require('bindings')('addon');++var fn = addon();+console.log(fn()); // 'hello world'\ No newline at end of file

src/1-getting-started/5_function_factory/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/1-getting-started/5_function_factory/nan/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "function_factory",+  "version": "0.0.0",+  "description": "Node.js Addons Example #5",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "nan": "^2.0.0"+  }+}

src/1-getting-started/5_function_factory/napi/addon.c

new file mode 100644@@ -0,0 +1,33 @@+#include <node_api.h>+#include <assert.h>++static napi_value MyFunction(napi_env env, napi_callback_info info) {+  napi_status status;++  napi_value str;+  status = napi_create_string_utf8(env, "hello world", NAPI_AUTO_LENGTH, &str);+  assert(status == napi_ok);++  return str;+}++static napi_value CreateFunction(napi_env env, napi_callback_info info) {+  napi_status status;++  napi_value fn;+  status = napi_create_function(+      env, "theFunction", NAPI_AUTO_LENGTH, MyFunction, NULL, &fn);+  assert(status == napi_ok);++  return fn;+}++static napi_value Init(napi_env env, napi_value exports) {+  napi_value new_exports;+  napi_status status = napi_create_function(+      env, "", NAPI_AUTO_LENGTH, CreateFunction, NULL, &new_exports);+  assert(status == napi_ok);+  return new_exports;+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/1-getting-started/5_function_factory/napi/addon.js

new file mode 100644@@ -0,0 +1,4 @@+var addon = require('bindings')('addon');++var fn = addon();+console.log(fn()); // 'hello world'

src/1-getting-started/5_function_factory/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.c" ]+    }+  ]+}

src/1-getting-started/5_function_factory/napi/package.json

new file mode 100644@@ -0,0 +1,11 @@+{+  "name": "function_factory",+  "version": "0.0.0",+  "description": "Node.js Addons Example #5",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0"+  }+}

src/1-getting-started/5_function_factory/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,18 @@+#include <napi.h>++Napi::String MyFunction(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  return Napi::String::New(env, "hello world");+}++Napi::Function CreateFunction(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  Napi::Function fn = Napi::Function::New(env, MyFunction, "theFunction");+  return fn;+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  return Napi::Function::New(env, CreateFunction, "createObject");+}++NODE_API_MODULE(addon, Init)

src/1-getting-started/5_function_factory/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,4 @@+var addon = require('bindings')('addon');++var fn = addon();+console.log(fn()); // 'hello world'

src/1-getting-started/5_function_factory/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "addon",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "addon.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/1-getting-started/5_function_factory/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "function_factory",+  "version": "0.0.0",+  "description": "Node.js Addons Example #5",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "node-addon-api": "^7.0.0"+  }+}

src/1-getting-started/6_object_wrap/nan/addon.cc

new file mode 100644@@ -0,0 +1,8 @@+#include <nan.h>+#include "myobject.h"++void InitAll(v8::Local<v8::Object> exports) {+  MyObject::Init(exports);+}++NODE_MODULE(addon, InitAll)

src/1-getting-started/6_object_wrap/nan/addon.js

new file mode 100644@@ -0,0 +1,13 @@+var addon = require('bindings')('addon');++var obj = new addon.MyObject(10);+console.log( obj.plusOne() ); // 11+console.log( obj.plusOne() ); // 12+console.log( obj.plusOne() ); // 13++console.log( obj.multiply().value() ); // 13+console.log( obj.multiply(10).value() ); // 130++var newobj = obj.multiply(-1);+console.log( newobj.value() ); // -13+console.log( obj === newobj ); // false

src/1-getting-started/6_object_wrap/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc", "myobject.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/1-getting-started/6_object_wrap/nan/myobject.cc

new file mode 100644@@ -0,0 +1,73 @@+#include "myobject.h"++Nan::Persistent<v8::Function> MyObject::constructor;++MyObject::MyObject(double value) : value_(value) {}++MyObject::~MyObject() {}++void MyObject::Init(v8::Local<v8::Object> exports) {+  v8::Local<v8::Context> context =+      exports->GetCreationContext().ToLocalChecked();+  Nan::HandleScope scope;++  // Prepare constructor template+  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);+  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());+  tpl->InstanceTemplate()->SetInternalFieldCount(1);++  // Prototype+  Nan::SetPrototypeMethod(tpl, "value", GetValue);+  Nan::SetPrototypeMethod(tpl, "plusOne", PlusOne);+  Nan::SetPrototypeMethod(tpl, "multiply", Multiply);++  constructor.Reset(tpl->GetFunction(context).ToLocalChecked());+  exports->Set(context,+               Nan::New("MyObject").ToLocalChecked(),+               tpl->GetFunction(context).ToLocalChecked());+}++void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();+  if (info.IsConstructCall()) {+    // Invoked as constructor: `new MyObject(...)`+    double value =+        info[0]->IsUndefined() ? 0 : info[0]->NumberValue(context).FromJust();+    MyObject* obj = new MyObject(value);+    obj->Wrap(info.This());+    info.GetReturnValue().Set(info.This());+  } else {+    // Invoked as plain function `MyObject(...)`, turn into construct call.+    const int argc = 1;+    v8::Local<v8::Value> argv[argc] = {info[0]};+    v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);+    info.GetReturnValue().Set(+        cons->NewInstance(context, argc, argv).ToLocalChecked());+  }+}++void MyObject::GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());+  info.GetReturnValue().Set(Nan::New(obj->value_));+}++void MyObject::PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());+  obj->value_ += 1;+  info.GetReturnValue().Set(Nan::New(obj->value_));+}++void MyObject::Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();+  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());+  double multiple =+      info[0]->IsUndefined() ? 1 : info[0]->NumberValue(context).FromJust();++  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);++  const int argc = 1;+  v8::Local<v8::Value> argv[argc] = {Nan::New(obj->value_ * multiple)};++  info.GetReturnValue().Set(+      cons->NewInstance(context, argc, argv).ToLocalChecked());+}

src/1-getting-started/6_object_wrap/nan/myobject.h

new file mode 100644@@ -0,0 +1,22 @@+#ifndef MYOBJECT_H+#define MYOBJECT_H++#include <nan.h>++class MyObject : public Nan::ObjectWrap {+ public:+  static void Init(v8::Local<v8::Object> exports);++ private:+  explicit MyObject(double value = 0);+  ~MyObject();++  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);+  static void GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info);+  static void PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info);+  static void Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info);+  static Nan::Persistent<v8::Function> constructor;+  double value_;+};++#endif

src/1-getting-started/6_object_wrap/nan/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "object_wrap",+  "version": "0.0.0",+  "description": "Node.js Addons Example #6",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "nan": "^2.14.0"+  }+}

src/1-getting-started/6_object_wrap/napi/addon.cc

new file mode 100644@@ -0,0 +1,7 @@+#include "myobject.h"++napi_value Init(napi_env env, napi_value exports) {+  return MyObject::Init(env, exports);+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/1-getting-started/6_object_wrap/napi/addon.js

new file mode 100644@@ -0,0 +1,13 @@+var addon = require('bindings')('addon');++var obj = new addon.MyObject(10);+console.log( obj.plusOne() ); // 11+console.log( obj.plusOne() ); // 12+console.log( obj.plusOne() ); // 13++console.log( obj.multiply().value ); // 13+console.log( obj.multiply(10).value ); // 130++var newobj = obj.multiply(-1);+console.log( newobj.value ); // -13+console.log( obj === newobj ); // false

src/1-getting-started/6_object_wrap/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc", "myobject.cc" ]+    }+  ]+}

src/1-getting-started/6_object_wrap/napi/myobject.cc

new file mode 100644@@ -0,0 +1,223 @@+#include "myobject.h"+#include <assert.h>++MyObject::MyObject(double value)+    : value_(value), env_(nullptr), wrapper_(nullptr) {}++MyObject::~MyObject() {+  napi_delete_reference(env_, wrapper_);+}++void MyObject::Destructor(napi_env env,+                          void* nativeObject,+                          void* /*finalize_hint*/) {+  reinterpret_cast<MyObject*>(nativeObject)->~MyObject();+}++#define DECLARE_NAPI_METHOD(name, func)                                        \+  { name, 0, func, 0, 0, 0, napi_default, 0 }++napi_value MyObject::Init(napi_env env, napi_value exports) {+  napi_status status;+  napi_property_descriptor properties[] = {+      {"value", 0, 0, GetValue, SetValue, 0, napi_default, 0},+      DECLARE_NAPI_METHOD("plusOne", PlusOne),+      DECLARE_NAPI_METHOD("multiply", Multiply),+  };++  napi_value cons;+  status = napi_define_class(+      env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 3, properties, &cons);+  assert(status == napi_ok);++  // We will need the constructor `cons` later during the life cycle of the+  // addon, so we store a persistent reference to it as the instance data for+  // our addon. This will enable us to use `napi_get_instance_data` at any+  // point during the life cycle of our addon to retrieve it. We cannot simply+  // store it as a global static variable, because that will render our addon+  // unable to support Node.js worker threads and multiple contexts on a single+  // thread.+  //+  // The finalizer we pass as a lambda will be called when our addon is unloaded+  // and is responsible for releasing the persistent reference and freeing the+  // heap memory where we stored the persistent reference.+  napi_ref* constructor = new napi_ref;+  status = napi_create_reference(env, cons, 1, constructor);+  assert(status == napi_ok);+  status = napi_set_instance_data(+      env,+      constructor,+      [](napi_env env, void* data, void* hint) {+        napi_ref* constructor = static_cast<napi_ref*>(data);+        napi_status status = napi_delete_reference(env, *constructor);+        assert(status == napi_ok);+        delete constructor;+      },+      nullptr);+  assert(status == napi_ok);++  status = napi_set_named_property(env, exports, "MyObject", cons);+  assert(status == napi_ok);+  return exports;+}++napi_value MyObject::Constructor(napi_env env) {+  void* instance_data = nullptr;+  napi_status status = napi_get_instance_data(env, &instance_data);+  assert(status == napi_ok);+  napi_ref* constructor = static_cast<napi_ref*>(instance_data);++  napi_value cons;+  status = napi_get_reference_value(env, *constructor, &cons);+  assert(status == napi_ok);+  return cons;+}++napi_value MyObject::New(napi_env env, napi_callback_info info) {+  napi_status status;++  napi_value target;+  status = napi_get_new_target(env, info, &target);+  assert(status == napi_ok);+  bool is_constructor = target != nullptr;++  if (is_constructor) {+    // Invoked as constructor: `new MyObject(...)`+    size_t argc = 1;+    napi_value args[1];+    napi_value jsthis;+    status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);+    assert(status == napi_ok);++    double value = 0;++    napi_valuetype valuetype;+    status = napi_typeof(env, args[0], &valuetype);+    assert(status == napi_ok);++    if (valuetype != napi_undefined) {+      status = napi_get_value_double(env, args[0], &value);+      assert(status == napi_ok);+    }++    MyObject* obj = new MyObject(value);++    obj->env_ = env;+    status = napi_wrap(env,+                       jsthis,+                       reinterpret_cast<void*>(obj),+                       MyObject::Destructor,+                       nullptr,  // finalize_hint+                       &obj->wrapper_);+    assert(status == napi_ok);++    return jsthis;+  } else {+    // Invoked as plain function `MyObject(...)`, turn into construct call.+    size_t argc_ = 1;+    napi_value args[1];+    status = napi_get_cb_info(env, info, &argc_, args, nullptr, nullptr);+    assert(status == napi_ok);++    const size_t argc = 1;+    napi_value argv[argc] = {args[0]};++    napi_value instance;+    status = napi_new_instance(env, Constructor(env), argc, argv, &instance);+    assert(status == napi_ok);++    return instance;+  }+}++napi_value MyObject::GetValue(napi_env env, napi_callback_info info) {+  napi_status status;++  napi_value jsthis;+  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);+  assert(status == napi_ok);++  MyObject* obj;+  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));+  assert(status == napi_ok);++  napi_value num;+  status = napi_create_double(env, obj->value_, &num);+  assert(status == napi_ok);++  return num;+}++napi_value MyObject::SetValue(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value value;+  napi_value jsthis;+  status = napi_get_cb_info(env, info, &argc, &value, &jsthis, nullptr);+  assert(status == napi_ok);++  MyObject* obj;+  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));+  assert(status == napi_ok);++  status = napi_get_value_double(env, value, &obj->value_);+  assert(status == napi_ok);++  return nullptr;+}++napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {+  napi_status status;++  napi_value jsthis;+  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);+  assert(status == napi_ok);++  MyObject* obj;+  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));+  assert(status == napi_ok);++  obj->value_ += 1;++  napi_value num;+  status = napi_create_double(env, obj->value_, &num);+  assert(status == napi_ok);++  return num;+}++napi_value MyObject::Multiply(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value args[1];+  napi_value jsthis;+  status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);+  assert(status == napi_ok);++  napi_valuetype valuetype;+  status = napi_typeof(env, args[0], &valuetype);+  assert(status == napi_ok);++  double multiple = 1;+  if (valuetype != napi_undefined) {+    status = napi_get_value_double(env, args[0], &multiple);+    assert(status == napi_ok);+  }++  MyObject* obj;+  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));+  assert(status == napi_ok);++  const int kArgCount = 1;+  napi_value argv[kArgCount];+  status = napi_create_double(env, obj->value_ * multiple, argv);+  assert(status == napi_ok);++  napi_value instance;+  status = napi_new_instance(env, Constructor(env), kArgCount, argv, &instance);+  assert(status == napi_ok);++  return instance;+}

src/1-getting-started/6_object_wrap/napi/myobject.h

new file mode 100644@@ -0,0 +1,27 @@+#ifndef TEST_ADDONS_NAPI_6_OBJECT_WRAP_MYOBJECT_H_+#define TEST_ADDONS_NAPI_6_OBJECT_WRAP_MYOBJECT_H_++#include <node_api.h>++class MyObject {+ public:+  static napi_value Init(napi_env env, napi_value exports);+  static void Destructor(napi_env env, void* nativeObject, void* finalize_hint);++ private:+  explicit MyObject(double value_ = 0);+  ~MyObject();++  static napi_value New(napi_env env, napi_callback_info info);+  static napi_value GetValue(napi_env env, napi_callback_info info);+  static napi_value SetValue(napi_env env, napi_callback_info info);+  static napi_value PlusOne(napi_env env, napi_callback_info info);+  static napi_value Multiply(napi_env env, napi_callback_info info);+  static inline napi_value Constructor(napi_env env);++  double value_;+  napi_env env_;+  napi_ref wrapper_;+};++#endif  // TEST_ADDONS_NAPI_6_OBJECT_WRAP_MYOBJECT_H_

src/1-getting-started/6_object_wrap/napi/package.json

new file mode 100644@@ -0,0 +1,11 @@+{+  "name": "object_wrap",+  "version": "0.0.0",+  "description": "Node.js Addons Example #6",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0"+  }+}

src/1-getting-started/6_object_wrap/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,8 @@+#include <napi.h>+#include "myobject.h"++Napi::Object InitAll(Napi::Env env, Napi::Object exports) {+  return MyObject::Init(env, exports);+}++NODE_API_MODULE(addon, InitAll)

src/1-getting-started/6_object_wrap/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,13 @@+var addon = require('bindings')('addon');++var obj = new addon.MyObject(10);+console.log( obj.plusOne() ); // 11+console.log( obj.plusOne() ); // 12+console.log( obj.plusOne() ); // 13++console.log( obj.multiply().value() ); // 13+console.log( obj.multiply(10).value() ); // 130++var newobj = obj.multiply(-1);+console.log( newobj.value() ); // -13+console.log( obj === newobj ); // false

src/1-getting-started/6_object_wrap/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "addon",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "addon.cc", "myobject.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/1-getting-started/6_object_wrap/node-addon-api/myobject.cc

new file mode 100644@@ -0,0 +1,58 @@+#include "myobject.h"++Napi::Object MyObject::Init(Napi::Env env, Napi::Object exports) {+  Napi::Function func =+      DefineClass(env,+                  "MyObject",+                  {InstanceMethod("plusOne", &MyObject::PlusOne),+                   InstanceMethod("value", &MyObject::GetValue),+                   InstanceMethod("multiply", &MyObject::Multiply)});++  Napi::FunctionReference* constructor = new Napi::FunctionReference();+  *constructor = Napi::Persistent(func);+  env.SetInstanceData(constructor);++  exports.Set("MyObject", func);+  return exports;+}++MyObject::MyObject(const Napi::CallbackInfo& info)+    : Napi::ObjectWrap<MyObject>(info) {+  Napi::Env env = info.Env();++  int length = info.Length();++  if (length <= 0 || !info[0].IsNumber()) {+    Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();+    return;+  }++  Napi::Number value = info[0].As<Napi::Number>();+  this->value_ = value.DoubleValue();+}++Napi::Value MyObject::GetValue(const Napi::CallbackInfo& info) {+  double num = this->value_;++  return Napi::Number::New(info.Env(), num);+}++Napi::Value MyObject::PlusOne(const Napi::CallbackInfo& info) {+  this->value_ = this->value_ + 1;++  return MyObject::GetValue(info);+}++Napi::Value MyObject::Multiply(const Napi::CallbackInfo& info) {+  Napi::Number multiple;+  if (info.Length() <= 0 || !info[0].IsNumber()) {+    multiple = Napi::Number::New(info.Env(), 1);+  } else {+    multiple = info[0].As<Napi::Number>();+  }++  Napi::Object obj = info.Env().GetInstanceData<Napi::FunctionReference>()->New(+      {Napi::Number::New(info.Env(), this->value_ * multiple.DoubleValue())});++  return obj;+}

src/1-getting-started/6_object_wrap/node-addon-api/myobject.h

new file mode 100644@@ -0,0 +1,19 @@+#ifndef MYOBJECT_H+#define MYOBJECT_H++#include <napi.h>++class MyObject : public Napi::ObjectWrap<MyObject> {+ public:+  static Napi::Object Init(Napi::Env env, Napi::Object exports);+  MyObject(const Napi::CallbackInfo& info);++ private:+  Napi::Value GetValue(const Napi::CallbackInfo& info);+  Napi::Value PlusOne(const Napi::CallbackInfo& info);+  Napi::Value Multiply(const Napi::CallbackInfo& info);++  double value_;+};++#endif

src/1-getting-started/6_object_wrap/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "object_wrap",+  "version": "0.0.0",+  "description": "Node.js Addons Example #6",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "engines": {+    "node": "~10 >=10.20 || >=12.17"+  },+  "dependencies": {+    "bindings": "~1.5.0",+    "node-addon-api": "^3.0.0"+  }+}

src/1-getting-started/7_factory_wrap/nan/addon.cc

new file mode 100644@@ -0,0 +1,23 @@+#include <nan.h>+#include "myobject.h"++void CreateObject(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  info.GetReturnValue().Set(MyObject::NewInstance(info[0]));+}++void InitAll(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {+  v8::Local<v8::Context> context =+      exports->GetCreationContext().ToLocalChecked();++  Nan::HandleScope scope;++  MyObject::Init();++  module->Set(context,+              Nan::New("exports").ToLocalChecked(),+              Nan::New<v8::FunctionTemplate>(CreateObject)+                  ->GetFunction(context)+                  .ToLocalChecked());+}++NODE_MODULE(addon, InitAll)

src/1-getting-started/7_factory_wrap/nan/addon.js

new file mode 100644@@ -0,0 +1,11 @@+var createObject = require('bindings')('addon');++var obj = createObject(10);+console.log( obj.plusOne() ); // 11+console.log( obj.plusOne() ); // 12+console.log( obj.plusOne() ); // 13++var obj2 = createObject(20);+console.log( obj2.plusOne() ); // 21+console.log( obj2.plusOne() ); // 22+console.log( obj2.plusOne() ); // 23

src/1-getting-started/7_factory_wrap/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc", "myobject.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/1-getting-started/7_factory_wrap/nan/myobject.cc

new file mode 100644@@ -0,0 +1,56 @@+#include "myobject.h"+#include <nan.h>++using namespace v8;++MyObject::MyObject(){};+MyObject::~MyObject(){};++Nan::Persistent<v8::Function> MyObject::constructor;++void MyObject::Init() {+  Nan::HandleScope scope;++  // Prepare constructor template+  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);+  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());+  tpl->InstanceTemplate()->SetInternalFieldCount(1);+  // Prototype+  tpl->PrototypeTemplate()->Set(Nan::New("plusOne").ToLocalChecked(),+                                Nan::New<v8::FunctionTemplate>(PlusOne));++  constructor.Reset(+      tpl->GetFunction(Nan::GetCurrentContext()).ToLocalChecked());+}++void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();++  MyObject* obj = new MyObject();+  obj->counter_ =+      info[0]->IsUndefined() ? 0 : info[0]->NumberValue(context).FromJust();+  obj->Wrap(info.This());++  info.GetReturnValue().Set(info.This());+}++v8::Local<v8::Object> MyObject::NewInstance(v8::Local<v8::Value> arg) {+  Nan::EscapableHandleScope scope;++  const unsigned argc = 1;+  v8::Local<v8::Value> argv[argc] = {arg};+  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);+  v8::Local<v8::Context> context =+      v8::Isolate::GetCurrent()->GetCurrentContext();+  v8::Local<v8::Object> instance =+      cons->NewInstance(context, argc, argv).ToLocalChecked();++  return scope.Escape(instance);+}++void MyObject::PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.This());+  obj->counter_ += 1;++  info.GetReturnValue().Set(Nan::New(obj->counter_));+}

src/1-getting-started/7_factory_wrap/nan/myobject.h

new file mode 100644@@ -0,0 +1,21 @@+#ifndef MYOBJECT_H+#define MYOBJECT_H++#include <nan.h>++class MyObject : public Nan::ObjectWrap {+ public:+  static void Init();+  static v8::Local<v8::Object> NewInstance(v8::Local<v8::Value> arg);++ private:+  MyObject();+  ~MyObject();++  static Nan::Persistent<v8::Function> constructor;+  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);+  static void PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info);+  double counter_;+};++#endif

src/1-getting-started/7_factory_wrap/nan/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "factory_wrap",+  "version": "0.0.0",+  "description": "Node.js Addons Example #7",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "nan": "^2.0.0"+  }+}

src/1-getting-started/7_factory_wrap/napi/addon.cc

new file mode 100644@@ -0,0 +1,30 @@+#include <assert.h>+#include "myobject.h"++napi_value CreateObject(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value args[1];+  status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);+  assert(status == napi_ok);++  napi_value instance;+  status = MyObject::NewInstance(env, args[0], &instance);+  assert(status == napi_ok);++  return instance;+}++napi_value Init(napi_env env, napi_value exports) {+  napi_status status = MyObject::Init(env);+  assert(status == napi_ok);++  napi_value new_exports;+  status = napi_create_function(+      env, "", NAPI_AUTO_LENGTH, CreateObject, nullptr, &new_exports);+  assert(status == napi_ok);+  return new_exports;+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/1-getting-started/7_factory_wrap/napi/addon.js

new file mode 100644@@ -0,0 +1,11 @@+var createObject = require('bindings')('addon');++var obj = createObject(10);+console.log( obj.plusOne() ); // 11+console.log( obj.plusOne() ); // 12+console.log( obj.plusOne() ); // 13++var obj2 = createObject(20);+console.log( obj2.plusOne() ); // 21+console.log( obj2.plusOne() ); // 22+console.log( obj2.plusOne() ); // 23

src/1-getting-started/7_factory_wrap/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc", "myobject.cc" ]+    }+  ]+}

src/1-getting-started/7_factory_wrap/napi/myobject.cc

new file mode 100644@@ -0,0 +1,137 @@+#include "myobject.h"+#include <assert.h>++MyObject::MyObject() : env_(nullptr), wrapper_(nullptr) {}++MyObject::~MyObject() {+  napi_delete_reference(env_, wrapper_);+}++void MyObject::Destructor(napi_env env,+                          void* nativeObject,+                          void* /*finalize_hint*/) {+  reinterpret_cast<MyObject*>(nativeObject)->~MyObject();+}++#define DECLARE_NAPI_METHOD(name, func)                                        \+  { name, 0, func, 0, 0, 0, napi_default, 0 }++napi_status MyObject::Init(napi_env env) {+  napi_status status;+  napi_property_descriptor properties[] = {+      DECLARE_NAPI_METHOD("plusOne", PlusOne),+  };++  napi_value cons;+  status = napi_define_class(+      env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 1, properties, &cons);+  if (status != napi_ok) return status;++  // We will need the constructor `cons` later during the life cycle of the+  // addon, so we store a persistent reference to it as the instance data for+  // our addon. This will enable us to use `napi_get_instance_data` at any+  // point during the life cycle of our addon to retrieve it. We cannot simply+  // store it as a global static variable, because that will render our addon+  // unable to support Node.js worker threads and multiple contexts on a single+  // thread.+  //+  // The finalizer we pass as a lambda will be called when our addon is unloaded+  // and is responsible for releasing the persistent reference and freeing the+  // heap memory where we stored the persistent reference.+  napi_ref* constructor = new napi_ref;+  status = napi_create_reference(env, cons, 1, constructor);+  assert(status == napi_ok);+  status = napi_set_instance_data(+      env,+      constructor,+      [](napi_env env, void* data, void* hint) {+        napi_ref* constructor = static_cast<napi_ref*>(data);+        napi_status status = napi_delete_reference(env, *constructor);+        assert(status == napi_ok);+        delete constructor;+      },+      nullptr);+  assert(status == napi_ok);++  return napi_ok;+}++napi_value MyObject::New(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value args[1];+  napi_value jsthis;+  status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);+  assert(status == napi_ok);++  napi_valuetype valuetype;+  status = napi_typeof(env, args[0], &valuetype);+  assert(status == napi_ok);++  MyObject* obj = new MyObject();++  if (valuetype == napi_undefined) {+    obj->counter_ = 0;+  } else {+    status = napi_get_value_double(env, args[0], &obj->counter_);+    assert(status == napi_ok);+  }++  obj->env_ = env;+  status = napi_wrap(env,+                     jsthis,+                     reinterpret_cast<void*>(obj),+                     MyObject::Destructor,+                     nullptr, /* finalize_hint */+                     &obj->wrapper_);+  assert(status == napi_ok);++  return jsthis;+}++napi_value MyObject::Constructor(napi_env env) {+  void* instance_data = nullptr;+  napi_status status = napi_get_instance_data(env, &instance_data);+  assert(status == napi_ok);+  napi_ref* constructor = static_cast<napi_ref*>(instance_data);++  napi_value cons;+  status = napi_get_reference_value(env, *constructor, &cons);+  assert(status == napi_ok);+  return cons;+}++napi_status MyObject::NewInstance(napi_env env,+                                  napi_value arg,+                                  napi_value* instance) {+  napi_status status;++  const int argc = 1;+  napi_value argv[argc] = {arg};++  status = napi_new_instance(env, Constructor(env), argc, argv, instance);+  if (status != napi_ok) return status;++  return napi_ok;+}++napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {+  napi_status status;++  napi_value jsthis;+  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);+  assert(status == napi_ok);++  MyObject* obj;+  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));+  assert(status == napi_ok);++  obj->counter_ += 1;++  napi_value num;+  status = napi_create_double(env, obj->counter_, &num);+  assert(status == napi_ok);++  return num;+}

src/1-getting-started/7_factory_wrap/napi/myobject.h

new file mode 100644@@ -0,0 +1,26 @@+#ifndef TEST_ADDONS_NAPI_7_FACTORY_WRAP_MYOBJECT_H_+#define TEST_ADDONS_NAPI_7_FACTORY_WRAP_MYOBJECT_H_++#include <node_api.h>++class MyObject {+ public:+  static napi_status Init(napi_env env);+  static void Destructor(napi_env env, void* nativeObject, void* finalize_hint);+  static napi_status NewInstance(napi_env env,+                                 napi_value arg,+                                 napi_value* instance);++ private:+  MyObject();+  ~MyObject();++  static inline napi_value Constructor(napi_env env);+  static napi_value New(napi_env env, napi_callback_info info);+  static napi_value PlusOne(napi_env env, napi_callback_info info);+  double counter_;+  napi_env env_;+  napi_ref wrapper_;+};++#endif  // TEST_ADDONS_NAPI_7_FACTORY_WRAP_MYOBJECT_H_

src/1-getting-started/7_factory_wrap/napi/package.json

new file mode 100644@@ -0,0 +1,11 @@+{+  "name": "factory_wrap",+  "version": "0.0.0",+  "description": "Node.js Addons Example #7",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0"+  }+}

src/1-getting-started/7_factory_wrap/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,14 @@+#include <napi.h>+#include "myobject.h"++Napi::Object CreateObject(const Napi::CallbackInfo& info) {+  return MyObject::NewInstance(info.Env(), info[0]);+}++Napi::Object InitAll(Napi::Env env, Napi::Object exports) {+  Napi::Object new_exports =+      Napi::Function::New(env, CreateObject, "CreateObject");+  return MyObject::Init(env, new_exports);+}++NODE_API_MODULE(addon, InitAll)

src/1-getting-started/7_factory_wrap/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,11 @@+var createObject = require('bindings')('addon');++var obj = createObject(10);+console.log( obj.plusOne() ); // 11+console.log( obj.plusOne() ); // 12+console.log( obj.plusOne() ); // 13++var obj2 = createObject(20);+console.log( obj2.plusOne() ); // 21+console.log( obj2.plusOne() ); // 22+console.log( obj2.plusOne() ); // 23

src/1-getting-started/7_factory_wrap/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "addon",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "addon.cc", "myobject.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      "defines": [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/1-getting-started/7_factory_wrap/node-addon-api/myobject.cc

new file mode 100644@@ -0,0 +1,35 @@+#include "myobject.h"+#include <napi.h>+#include <uv.h>++using namespace Napi;++Napi::Object MyObject::Init(Napi::Env env, Napi::Object exports) {+  Napi::Function func = DefineClass(+      env, "MyObject", {InstanceMethod("plusOne", &MyObject::PlusOne)});++  Napi::FunctionReference* constructor = new Napi::FunctionReference();+  *constructor = Napi::Persistent(func);+  env.SetInstanceData(constructor);++  exports.Set("MyObject", func);+  return exports;+}++MyObject::MyObject(const Napi::CallbackInfo& info)+    : Napi::ObjectWrap<MyObject>(info) {+  this->counter_ = info[0].As<Napi::Number>().DoubleValue();+};++Napi::Object MyObject::NewInstance(Napi::Env env, Napi::Value arg) {+  Napi::EscapableHandleScope scope(env);+  Napi::Object obj = env.GetInstanceData<Napi::FunctionReference>()->New({arg});+  return scope.Escape(napi_value(obj)).ToObject();+}++Napi::Value MyObject::PlusOne(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  this->counter_ = this->counter_ + 1;++  return Napi::Number::New(env, this->counter_);+}

src/1-getting-started/7_factory_wrap/node-addon-api/myobject.h

new file mode 100644@@ -0,0 +1,17 @@+#ifndef MYOBJECT_H+#define MYOBJECT_H++#include <napi.h>++class MyObject : public Napi::ObjectWrap<MyObject> {+ public:+  static Napi::Object Init(Napi::Env env, Napi::Object exports);+  static Napi::Object NewInstance(Napi::Env env, Napi::Value arg);+  MyObject(const Napi::CallbackInfo& info);++ private:+  Napi::Value PlusOne(const Napi::CallbackInfo& info);+  double counter_;+};++#endif

src/1-getting-started/7_factory_wrap/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "factory_wrap",+  "version": "0.0.0",+  "description": "Node.js Addons Example #7",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "engines": {+    "node": "~10 >=10.20 || >=12.17"+  },+  "dependencies": {+    "bindings": "~1.2.1",+    "node-addon-api": "^7.0.0"+  }+}

src/1-getting-started/a-first-project/node-addon-api/README.md

new file mode 100644@@ -0,0 +1,14 @@+# Node-API A First Project++This is an example project that accompanies the Node-API workshop tutorials++A tutorial describing this project can be found at the [Node-API Resource](https://napi.inspiredware.com/getting-started/first.html).++To build and run this program on your system, clone it to your computer and run these two commands inside your clone:++```+npm install+npm test+```++> You need to have Node 10.5.0 or later installed. \ No newline at end of file

src/1-getting-started/a-first-project/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,20 @@+{+  'targets': [+    {+      'target_name': 'hello-world-native',+      'sources': [ 'src/hello_world.cc' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'xcode_settings': {+        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+        'CLANG_CXX_LIBRARY': 'libc++',+        'MACOSX_DEPLOYMENT_TARGET': '10.7'+      },+      'msvs_settings': {+        'VCCLCompilerTool': { 'ExceptionHandling': 1 },+      }+    }+  ]+}\ No newline at end of file

src/1-getting-started/a-first-project/node-addon-api/lib/binding.js

new file mode 100644@@ -0,0 +1,4 @@+const addon = require('../build/Release/hello-world-native');++module.exports = addon.HelloWorld+

src/1-getting-started/a-first-project/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,16 @@+{+  "main": "lib/binding.js",+  "private": true,+  "dependencies": {+    "node-addon-api": "^1.1.0"+  },+  "scripts": {+    "test": "node --napi-modules ./test/test_binding.js"+  },+  "gypfile": true,+  "name": "hello-world",+  "version": "1.0.0",+  "description": "A first project.",+  "author": "Your name goes here",+  "license": "ISC"+}

src/1-getting-started/a-first-project/node-addon-api/src/hello_world.cc

new file mode 100644@@ -0,0 +1,16 @@+#include <napi.h>++using namespace Napi;++Napi::String Method(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  return Napi::String::New(env, "world");+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "HelloWorld"),+              Napi::Function::New(env, Method));+  return exports;+}++NODE_API_MODULE(addon, Init)

src/1-getting-started/a-first-project/node-addon-api/test/test_binding.js

new file mode 100644@@ -0,0 +1,14 @@+const HelloWorld = require("../lib/binding.js");+const assert = require("assert");++assert(HelloWorld, "The expected function is undefined");++function testBasic()+{+    const result =  HelloWorld("hello");+    assert.strictEqual(result, "world", "Unexpected value returned");+}++assert.doesNotThrow(testBasic, undefined, "testBasic threw an expection");++console.log("Tests passed- everything looks OK!");\ No newline at end of file

src/2-js-to-native-conversion/8_passing_wrapped/nan/addon.cc

new file mode 100644@@ -0,0 +1,40 @@+#include <nan.h>+#include "myobject.h"++using namespace v8;++void CreateObject(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  info.GetReturnValue().Set(MyObject::NewInstance(info[0]));+}++void Add(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();++  MyObject* obj1 = Nan::ObjectWrap::Unwrap<MyObject>(+      info[0]->ToObject(context).ToLocalChecked());+  MyObject* obj2 = Nan::ObjectWrap::Unwrap<MyObject>(+      info[1]->ToObject(context).ToLocalChecked());+  double sum = obj1->Val() + obj2->Val();+  info.GetReturnValue().Set(Nan::New(sum));+}++void InitAll(v8::Local<v8::Object> exports) {+  v8::Local<v8::Context> context =+      exports->GetCreationContext().ToLocalChecked();++  MyObject::Init();++  exports->Set(context,+               Nan::New("createObject").ToLocalChecked(),+               Nan::New<v8::FunctionTemplate>(CreateObject)+                   ->GetFunction(context)+                   .ToLocalChecked());++  exports->Set(context,+               Nan::New("add").ToLocalChecked(),+               Nan::New<v8::FunctionTemplate>(Add)+                   ->GetFunction(context)+                   .ToLocalChecked());+}++NODE_MODULE(addon, InitAll)

src/2-js-to-native-conversion/8_passing_wrapped/nan/addon.js

new file mode 100644@@ -0,0 +1,7 @@+var addon = require('bindings')('addon');++var obj1 = addon.createObject(10);+var obj2 = addon.createObject(20);+var result = addon.add(obj1, obj2);++console.log(result); // 30

src/2-js-to-native-conversion/8_passing_wrapped/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc", "myobject.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/2-js-to-native-conversion/8_passing_wrapped/nan/myobject.cc

new file mode 100644@@ -0,0 +1,43 @@+#include "myobject.h"+#include <node.h>++MyObject::MyObject(){};+MyObject::~MyObject(){};++Nan::Persistent<v8::Function> MyObject::constructor;++void MyObject::Init() {+  Nan::HandleScope scope;++  // Prepare constructor template+  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);+  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());+  tpl->InstanceTemplate()->SetInternalFieldCount(1);++  constructor.Reset(+      tpl->GetFunction(Nan::GetCurrentContext()).ToLocalChecked());+}++void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {+  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();+  MyObject* obj = new MyObject();+  obj->val_ =+      info[0]->IsUndefined() ? 0 : info[0]->NumberValue(context).FromJust();+  obj->Wrap(info.This());++  info.GetReturnValue().Set(info.This());+}++v8::Local<v8::Object> MyObject::NewInstance(v8::Local<v8::Value> arg) {+  Nan::EscapableHandleScope scope;++  const unsigned argc = 1;+  v8::Local<v8::Value> argv[argc] = {arg};+  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);+  v8::Local<v8::Context> context =+      v8::Isolate::GetCurrent()->GetCurrentContext();+  v8::Local<v8::Object> instance =+      cons->NewInstance(context, argc, argv).ToLocalChecked();++  return scope.Escape(instance);+}

src/2-js-to-native-conversion/8_passing_wrapped/nan/myobject.h

new file mode 100644@@ -0,0 +1,21 @@+#ifndef MYOBJECT_H+#define MYOBJECT_H++#include <nan.h>++class MyObject : public Nan::ObjectWrap {+ public:+  static void Init();+  static v8::Local<v8::Object> NewInstance(v8::Local<v8::Value> arg);+  double Val() const { return val_; }++ private:+  MyObject();+  ~MyObject();++  static Nan::Persistent<v8::Function> constructor;+  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);+  double val_;+};++#endif

src/2-js-to-native-conversion/8_passing_wrapped/nan/package.json

new file mode 100644@@ -0,0 +1,12 @@+{+  "name": "passing_wrapped",+  "version": "0.0.0",+  "description": "Node.js Addons Example #8",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0",+    "nan": "^2.0.0"+  }+}

src/2-js-to-native-conversion/8_passing_wrapped/napi/addon.cc

new file mode 100644@@ -0,0 +1,59 @@+#include <assert.h>+#include "myobject.h"++napi_value CreateObject(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value args[1];+  status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);+  assert(status == napi_ok);++  napi_value instance;+  status = MyObject::NewInstance(env, args[0], &instance);++  return instance;+}++napi_value Add(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 2;+  napi_value args[2];+  status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);+  assert(status == napi_ok);++  MyObject* obj1;+  status = napi_unwrap(env, args[0], reinterpret_cast<void**>(&obj1));+  assert(status == napi_ok);++  MyObject* obj2;+  status = napi_unwrap(env, args[1], reinterpret_cast<void**>(&obj2));+  assert(status == napi_ok);++  napi_value sum;+  status = napi_create_double(env, obj1->Val() + obj2->Val(), &sum);+  assert(status == napi_ok);++  return sum;+}++#define DECLARE_NAPI_METHOD(name, func)                                        \+  { name, 0, func, 0, 0, 0, napi_default, 0 }++napi_value Init(napi_env env, napi_value exports) {+  napi_status status;++  MyObject::Init(env);++  napi_property_descriptor desc[] = {+      DECLARE_NAPI_METHOD("createObject", CreateObject),+      DECLARE_NAPI_METHOD("add", Add),+  };+  status =+      napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc);+  assert(status == napi_ok);+  return exports;+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

src/2-js-to-native-conversion/8_passing_wrapped/napi/addon.js

new file mode 100644@@ -0,0 +1,7 @@+var addon = require('bindings')('addon');++var obj1 = addon.createObject(10);+var obj2 = addon.createObject(20);+var result = addon.add(obj1, obj2);++console.log(result); // 30

src/2-js-to-native-conversion/8_passing_wrapped/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [ "addon.cc", "myobject.cc" ]+    }+  ]+}

src/2-js-to-native-conversion/8_passing_wrapped/napi/myobject.cc

new file mode 100644@@ -0,0 +1,111 @@+#include "myobject.h"+#include <assert.h>++MyObject::MyObject() : env_(nullptr), wrapper_(nullptr) {}++MyObject::~MyObject() {+  napi_delete_reference(env_, wrapper_);+}++void MyObject::Destructor(napi_env env,+                          void* nativeObject,+                          void* /*finalize_hint*/) {+  reinterpret_cast<MyObject*>(nativeObject)->~MyObject();+}++napi_status MyObject::Init(napi_env env) {+  napi_status status;++  napi_value cons;+  status = napi_define_class(+      env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 0, nullptr, &cons);+  if (status != napi_ok) return status;++  // We will need the constructor `cons` later during the life cycle of the+  // application, so we store a persistent reference to it as the instance data+  // for our addon. This will enable us to use `napi_get_instance_data` at any+  // point during the life cycle of our addon to retrieve it. We cannot simply+  // store it as a global static variable, because that will render our addon+  // unable to support Node.js worker threads and multiple contexts on a single+  // thread.+  //+  // The finalizer we pass as a lambda will be called when our addon is unloaded+  // and is responsible for releasing the persistent reference and freeing the+  // heap memory where we stored the persistent reference.+  napi_ref* constructor = new napi_ref;+  status = napi_create_reference(env, cons, 1, constructor);+  assert(status == napi_ok);+  status = napi_set_instance_data(+      env,+      constructor,+      [](napi_env env, void* data, void* hint) {+        napi_ref* constructor = static_cast<napi_ref*>(data);+        napi_status status = napi_delete_reference(env, *constructor);+        assert(status == napi_ok);+        delete constructor;+      },+      nullptr);+  assert(status == napi_ok);++  return napi_ok;+}++napi_value MyObject::New(napi_env env, napi_callback_info info) {+  napi_status status;++  size_t argc = 1;+  napi_value args[1];+  napi_value jsthis;+  status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);+  assert(status == napi_ok);++  MyObject* obj = new MyObject();++  napi_valuetype valuetype;+  status = napi_typeof(env, args[0], &valuetype);+  assert(status == napi_ok);++  if (valuetype == napi_undefined) {+    obj->val_ = 0;+  } else {+    status = napi_get_value_double(env, args[0], &obj->val_);+    assert(status == napi_ok);+  }++  obj->env_ = env;+  status = napi_wrap(env,+                     jsthis,+                     reinterpret_cast<void*>(obj),+                     MyObject::Destructor,+                     nullptr,  // finalize_hint+                     &obj->wrapper_);+  assert(status == napi_ok);++  return jsthis;+}++napi_value MyObject::Constructor(napi_env env) {+  void* instance_data = nullptr;+  napi_status status = napi_get_instance_data(env, &instance_data);+  assert(status == napi_ok);+  napi_ref* constructor = static_cast<napi_ref*>(instance_data);++  napi_value cons;+  status = napi_get_reference_value(env, *constructor, &cons);+  assert(status == napi_ok);+  return cons;+}++napi_status MyObject::NewInstance(napi_env env,+                                  napi_value arg,+                                  napi_value* instance) {+  napi_status status;++  const int argc = 1;+  napi_value argv[argc] = {arg};++  status = napi_new_instance(env, Constructor(env), argc, argv, instance);+  if (status != napi_ok) return status;++  return napi_ok;+}

src/2-js-to-native-conversion/8_passing_wrapped/napi/myobject.h

new file mode 100644@@ -0,0 +1,26 @@+#ifndef TEST_ADDONS_NAPI_8_PASSING_WRAPPED_MYOBJECT_H_+#define TEST_ADDONS_NAPI_8_PASSING_WRAPPED_MYOBJECT_H_++#include <node_api.h>++class MyObject {+ public:+  static napi_status Init(napi_env env);+  static void Destructor(napi_env env, void* nativeObject, void* finalize_hint);+  static napi_status NewInstance(napi_env env,+                                 napi_value arg,+                                 napi_value* instance);+  double Val() const { return val_; }++ private:+  MyObject();+  ~MyObject();++  static inline napi_value Constructor(napi_env env);+  static napi_value New(napi_env env, napi_callback_info info);+  double val_;+  napi_env env_;+  napi_ref wrapper_;+};++#endif  // TEST_ADDONS_NAPI_8_PASSING_WRAPPED_MYOBJECT_H_

src/2-js-to-native-conversion/8_passing_wrapped/napi/package.json

new file mode 100644@@ -0,0 +1,11 @@+{+  "name": "passing_wrapped",+  "version": "0.0.0",+  "description": "Node.js Addons Example #8",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.5.0"+  }+}

src/2-js-to-native-conversion/8_passing_wrapped/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,31 @@+#include <napi.h>+#include "myobject.h"++using namespace Napi;++Napi::Object CreateObject(const Napi::CallbackInfo& info) {+  return MyObject::NewInstance(info.Env(), info[0]);+}++Napi::Number Add(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  MyObject* obj1 =+      Napi::ObjectWrap<MyObject>::Unwrap(info[0].As<Napi::Object>());+  MyObject* obj2 =+      Napi::ObjectWrap<MyObject>::Unwrap(info[1].As<Napi::Object>());+  double sum = obj1->Val() + obj2->Val();+  return Napi::Number::New(env, sum);+}++Napi::Object InitAll(Napi::Env env, Napi::Object exports) {+  MyObject::Init(env, exports);++  exports.Set(Napi::String::New(env, "createObject"),+              Napi::Function::New(env, CreateObject));++  exports.Set(Napi::String::New(env, "add"), Napi::Function::New(env, Add));++  return exports;+}++NODE_API_MODULE(addon, InitAll)

src/2-js-to-native-conversion/8_passing_wrapped/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,7 @@+var addon = require('bindings')('addon');++var obj1 = addon.createObject(10);+var obj2 = addon.createObject(20);+var result = addon.add(obj1, obj2);++console.log(result); // 30

src/2-js-to-native-conversion/8_passing_wrapped/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,16 @@+{+  "targets": [+    {+      "target_name": "addon",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "addon.cc", "myobject.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/2-js-to-native-conversion/8_passing_wrapped/node-addon-api/myobject.cc

new file mode 100644@@ -0,0 +1,25 @@+#include "myobject.h"+#include <napi.h>+#include <uv.h>++MyObject::MyObject(const Napi::CallbackInfo& info)+    : Napi::ObjectWrap<MyObject>(info) {+  this->val_ = info[0].As<Napi::Number>().DoubleValue();+};++void MyObject::Init(Napi::Env env, Napi::Object exports) {+  Napi::Function func = DefineClass(env, "MyObject", {});++  Napi::FunctionReference* constructor = new Napi::FunctionReference();+  *constructor = Napi::Persistent(func);+  env.SetInstanceData(constructor);  // NOTE: this assumes only 1 class is+                                     // exported for multiple exported classes,+                                     // need a struct or other mechanism++  exports.Set("MyObject", func);+}++Napi::Object MyObject::NewInstance(Napi::Env env, Napi::Value arg) {+  Napi::Object obj = env.GetInstanceData<Napi::FunctionReference>()->New({arg});+  return obj;+}

src/2-js-to-native-conversion/8_passing_wrapped/node-addon-api/myobject.h

new file mode 100644@@ -0,0 +1,17 @@+#ifndef MYOBJECT_H+#define MYOBJECT_H++#include <napi.h>++class MyObject : public Napi::ObjectWrap<MyObject> {+ public:+  static void Init(Napi::Env env, Napi::Object exports);+  static Napi::Object NewInstance(Napi::Env env, Napi::Value arg);+  double Val() const { return val_; }+  MyObject(const Napi::CallbackInfo& info);++ private:+  double val_;+};++#endif

src/2-js-to-native-conversion/8_passing_wrapped/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "passing_wrapped",+  "version": "0.0.0",+  "description": "Node.js Addons Example #8",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "engines": {+    "node": "~10 >=10.20 || >=12.17"+  },+  "dependencies": {+    "bindings": "~1.5.0",+    "node-addon-api": "^3.0.0"+  }+}

src/2-js-to-native-conversion/array_buffer_to_native/node-addon-api/array_buffer_to_native.cc

new file mode 100644@@ -0,0 +1,35 @@+#include <napi.h>+#include <stdio.h>++static void ArrayConsumer(const int32_t* array, size_t length) {+  for (size_t index = 0; index < length; index++) {+    fprintf(stderr, "array[%lu] = %d\n", index, array[index]);+  }+}++static Napi::Value AcceptArrayBuffer(const Napi::CallbackInfo& info) {+  if (info.Length() != 1) {+    Napi::Error::New(info.Env(), "Expected exactly one argument")+        .ThrowAsJavaScriptException();+    return info.Env().Undefined();+  }+  if (!info[0].IsArrayBuffer()) {+    Napi::Error::New(info.Env(), "Expected an ArrayBuffer")+        .ThrowAsJavaScriptException();+    return info.Env().Undefined();+  }++  Napi::ArrayBuffer buf = info[0].As<Napi::ArrayBuffer>();++  ArrayConsumer(reinterpret_cast<int32_t*>(buf.Data()),+                buf.ByteLength() / sizeof(int32_t));++  return info.Env().Undefined();+}++static Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports["AcceptArrayBuffer"] = Napi::Function::New(env, AcceptArrayBuffer);+  return exports;+}++NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

src/2-js-to-native-conversion/array_buffer_to_native/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "array_buffer_to_native",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "array_buffer_to_native.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/2-js-to-native-conversion/array_buffer_to_native/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,15 @@+const binding = require('bindings')('array_buffer_to_native');+const array = new Int32Array(10);++array[0] = 19;+array[1] = -41;+array[2] = 98;+array[3] = -922;+array[4] = 587;+array[5] = 12;+array[6] = 221;+array[7] = 49;+array[8] = -96;+array[9] = -1;++binding.AcceptArrayBuffer(array.buffer);

src/2-js-to-native-conversion/array_buffer_to_native/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,14 @@+{+  "name": "array_buffer_to_native",+  "version": "0.0.0",+  "description": "Fill Out a Native Array in JavaScript",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "node-addon-api": "^1.0.0"+  },+  "scripts": {+    "test": "node index.js"+  }+}

src/2-js-to-native-conversion/object-template-demo/README.md

new file mode 100644@@ -0,0 +1,3 @@+The goal of this demo is to show how to implement V8 ObjectTemplate-like handlers.+NAN uses the ObjectTemplate directly: the code is adapted from NAN namedinterceptors unit test.+Node-API cannot use the ObjectTemplate: it uses the JavaScript Proxy object to get similar behavior.

src/2-js-to-native-conversion/object-template-demo/nan/binding.gyp

new file mode 100644@@ -0,0 +1,11 @@+{+  "targets": [+    {+      "target_name": "object-template-demo",+      "sources": [ "object-template-demo.cc" ],+      "include_dirs": [+        "<!(node -e \"require('nan')\")"+      ]+    }+  ]+}

src/2-js-to-native-conversion/object-template-demo/nan/index.js

new file mode 100644@@ -0,0 +1,10 @@+const addon = require('bindings')('object-template-demo');++const interceptor = addon.create();+console.log(interceptor.prop); // 'foo'+interceptor.prop = 'setting a value';+console.log(interceptor.prop); // 'setting a value'+delete interceptor.something;+console.log(interceptor.prop); // 'goober';+console.log(Object.prototype.hasOwnProperty.call(interceptor, "thing")); // true+console.log(Object.keys(interceptor)[0]); // 'value'

src/2-js-to-native-conversion/object-template-demo/nan/object-template-demo.cc

new file mode 100644@@ -0,0 +1,118 @@+/*********************************************************************+ * NAN - Native Abstractions for Node.js+ *+ * Copyright (c) 2018 NAN contributors+ *+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>+ ********************************************************************/++#include <nan.h>+#include <cstring>++using namespace Nan;  // NOLINT(build/namespaces)++class NamedInterceptor : public ObjectWrap {+  char buf[256];++ public:+  NamedInterceptor() { std::strncpy(this->buf, "foo", sizeof(this->buf)); }+  static NAN_MODULE_INIT(Init);+  static v8::Local<v8::Value> NewInstance();+  static NAN_METHOD(New);++  static NAN_PROPERTY_GETTER(PropertyGetter);+  static NAN_PROPERTY_SETTER(PropertySetter);+  static NAN_PROPERTY_ENUMERATOR(PropertyEnumerator);+  static NAN_PROPERTY_DELETER(PropertyDeleter);+  static NAN_PROPERTY_QUERY(PropertyQuery);+};++static Persistent<v8::FunctionTemplate> namedinterceptors_constructor;++NAN_METHOD(CreateNew) {+  info.GetReturnValue().Set(NamedInterceptor::NewInstance());+}++NAN_MODULE_INIT(NamedInterceptor::Init) {+  v8::Local<v8::FunctionTemplate> tpl =+      Nan::New<v8::FunctionTemplate>(NamedInterceptor::New);+  namedinterceptors_constructor.Reset(tpl);+  tpl->SetClassName(Nan::New("NamedInterceptor").ToLocalChecked());+  tpl->InstanceTemplate()->SetInternalFieldCount(1);+  v8::Local<v8::ObjectTemplate> inst = tpl->InstanceTemplate();++  SetNamedPropertyHandler(inst,+                          NamedInterceptor::PropertyGetter,+                          NamedInterceptor::PropertySetter,+                          NamedInterceptor::PropertyQuery,+                          NamedInterceptor::PropertyDeleter,+                          NamedInterceptor::PropertyEnumerator);++  v8::Local<v8::Function> createnew =+      Nan::GetFunction(Nan::New<v8::FunctionTemplate>(CreateNew))+          .ToLocalChecked();+  Set(target, Nan::New("create").ToLocalChecked(), createnew);+}++v8::Local<v8::Value> NamedInterceptor::NewInstance() {+  EscapableHandleScope scope;+  v8::Local<v8::FunctionTemplate> constructorHandle =+      Nan::New(namedinterceptors_constructor);+  v8::Local<v8::Object> instance =+      Nan::NewInstance(GetFunction(constructorHandle).ToLocalChecked())+          .ToLocalChecked();+  return scope.Escape(instance);+}++NAN_METHOD(NamedInterceptor::New) {+  NamedInterceptor* interceptor = new NamedInterceptor();+  interceptor->Wrap(info.This());+  info.GetReturnValue().Set(info.This());+}++NAN_PROPERTY_GETTER(NamedInterceptor::PropertyGetter) {+  NamedInterceptor* interceptor =+      ObjectWrap::Unwrap<NamedInterceptor>(info.Holder());+  if (!std::strcmp(*Nan::Utf8String(property), "prop")) {+    info.GetReturnValue().Set(Nan::New(interceptor->buf).ToLocalChecked());+  } else {+    info.GetReturnValue().Set(Nan::New("bar").ToLocalChecked());+  }+}++NAN_PROPERTY_SETTER(NamedInterceptor::PropertySetter) {+  NamedInterceptor* interceptor =+      ObjectWrap::Unwrap<NamedInterceptor>(info.Holder());+  if (!std::strcmp(*Nan::Utf8String(property), "prop")) {+    std::strncpy(+        interceptor->buf, *Nan::Utf8String(value), sizeof(interceptor->buf));+    info.GetReturnValue().Set(info.This());+  } else {+    info.GetReturnValue().Set(info.This());+  }+}++NAN_PROPERTY_ENUMERATOR(NamedInterceptor::PropertyEnumerator) {+  v8::Local<v8::Array> arr = Nan::New<v8::Array>();+  Set(arr, 0, Nan::New("value").ToLocalChecked());+  info.GetReturnValue().Set(arr);+}++NAN_PROPERTY_DELETER(NamedInterceptor::PropertyDeleter) {+  NamedInterceptor* interceptor =+      ObjectWrap::Unwrap<NamedInterceptor>(info.Holder());+  std::strncpy(interceptor->buf, "goober", sizeof(interceptor->buf));+  info.GetReturnValue().Set(True());+}++NAN_PROPERTY_QUERY(NamedInterceptor::PropertyQuery) {+  Nan::Utf8String s(property);+  if (!std::strcmp(*s, "thing")) {+    return info.GetReturnValue().Set(Nan::New<v8::Integer>(v8::DontEnum));+  }+  if (!std::strcmp(*s, "value")) {+    return info.GetReturnValue().Set(Nan::New(0));+  }+}++NODE_MODULE(namedinterceptors, NamedInterceptor::Init)

src/2-js-to-native-conversion/object-template-demo/nan/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "object-template-demo",+  "version": "0.0.0",+  "description": "Intercept named property access using V8 ObjectTemplate",+  "main": "index.js",+  "private": true,+  "gypfile": true,+  "scripts": {+    "test": "node index.js"+  },+  "dependencies": {+    "bindings": "~1.5.0",+    "nan": "^2.14.0"+  }+}

src/2-js-to-native-conversion/object-template-demo/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  "targets": [+    {+      "target_name": "object_template_demo",+      "sources": [ "object-template-demo.cc", "proxy-template.cc" ]+    }+  ]+}

src/2-js-to-native-conversion/object-template-demo/napi/index.js

new file mode 100644@@ -0,0 +1,10 @@+const addon = require('bindings')('object_template_demo');++const interceptor = addon.create();+console.log(interceptor.prop); // 'foo'+interceptor.prop = 'setting a value';+console.log(interceptor.prop); // 'setting a value'+delete interceptor.something;+console.log(interceptor.prop); // 'goober';+console.log(Object.prototype.hasOwnProperty.call(interceptor, "thing")); // true+console.log(Object.keys(interceptor)[0]); // 'value'

src/2-js-to-native-conversion/object-template-demo/napi/node-api-common.h

new file mode 100644@@ -0,0 +1,141 @@+#include <node_api.h>+#include <initializer_list>+#include <utility>++// Empty value so that macros here are able to return NULL or void+#define NODE_API_RETVAL_NOTHING  // Intentionally blank #define++#define GET_AND_THROW_LAST_ERROR(env)                                          \+  do {                                                                         \+    const napi_extended_error_info* error_info;                                \+    napi_get_last_error_info((env), &error_info);                              \+    bool is_pending;                                                           \+    const char* err_message = error_info->error_message;                       \+    napi_is_exception_pending((env), &is_pending);                             \+    /* If an exception is already pending, don't rethrow it */                 \+    if (!is_pending) {                                                         \+      const char* error_message =                                              \+          err_message != NULL ? err_message : "empty error message";           \+      napi_throw_error((env), NULL, error_message);                            \+    }                                                                          \+  } while (0)++#define NODE_API_ASSERT_BASE(env, assertion, message, ret_val)                 \+  do {                                                                         \+    if (!(assertion)) {                                                        \+      napi_throw_error(                                                        \+          (env), NULL, "assertion (" #assertion ") failed: " message);         \+      return ret_val;                                                          \+    }                                                                          \+  } while (0)++// Returns NULL on failed assertion.+// This is meant to be used inside napi_callback methods.+#define NODE_API_ASSERT(env, assertion, message)                               \+  NODE_API_ASSERT_BASE(env, assertion, message, NULL)++#define NODE_API_CALL_BASE(env, the_call, ret_val)                             \+  do {                                                                         \+    if ((the_call) != napi_ok) {                                               \+      GET_AND_THROW_LAST_ERROR((env));                                         \+      return ret_val;                                                          \+    }                                                                          \+  } while (0)++// Returns NULL if the_call doesn't return napi_ok.+#define NODE_API_CALL(env, the_call) NODE_API_CALL_BASE(env, the_call, NULL)++// Returns empty if the_call doesn't return napi_ok.+#define NODE_API_CALL_RETURN_VOID(env, the_call)                               \+  NODE_API_CALL_BASE(env, the_call, NODE_API_RETVAL_NOTHING)++#define CHECK_NAPI(...)                                                        \+  do {                                                                         \+    napi_status res__ = (__VA_ARGS__);                                         \+    if (res__ != napi_ok) {                                                    \+      return res__;                                                            \+    }                                                                          \+  } while (0)++#define NAPI_CALL(expr) NODE_API_CALL(env, expr);++#ifdef __cpp_lib_span+#include <span>+using std::span;+#else+/**+ * @brief A span of values that can be used to pass arguments to function.+ *+ * For C++20 we should consider to replace it with std::span.+ */+template <typename T>+struct span {+  constexpr span(std::initializer_list<T> il) noexcept+      : data_{const_cast<T*>(il.begin())}, size_{il.size()} {}+  constexpr span(T* data, size_t size) noexcept : data_{data}, size_{size} {}+  [[nodiscard]] constexpr T* data() const noexcept { return data_; }+  [[nodiscard]] constexpr size_t size() const noexcept { return size_; }+  [[nodiscard]] constexpr T* begin() const noexcept { return data_; }+  [[nodiscard]] constexpr T* end() const noexcept { return data_ + size_; }+  const T& operator[](size_t index) const noexcept { return *(data_ + index); }++ private:+  T* data_;+  size_t size_;+};+#endif  // __cpp_lib_span++struct RefHolder {+  RefHolder(std::nullptr_t = nullptr) noexcept {}+  explicit RefHolder(napi_env env, napi_value value) : env_(env) {+    // Start with 2 to avoid ever going to 0 that creates a weak ref.+    napi_create_reference(env, value, 2, &ref_);+  }++  // The class is movable.+  RefHolder(RefHolder&& other) noexcept+      : env_(std::exchange(other.env_, nullptr)),+        ref_(std::exchange(other.ref_, nullptr)) {}++  RefHolder& operator=(RefHolder&& other) noexcept {+    if (this != &other) {+      swap(*this, other);+      RefHolder temp(std::move(other));+    }+    return *this;+  }++  // The class is not copyable.+  RefHolder(const RefHolder& other) = delete;+  RefHolder& operator=(const RefHolder& other) = delete;++  ~RefHolder() noexcept {+    if (env_ != nullptr && ref_ != nullptr) {+      uint32_t refCount{};+      napi_reference_unref(env_, ref_, &refCount);+      if (refCount == 1) {+        napi_delete_reference(env_, ref_);+      }+    }+  }++  operator napi_value() const {+    napi_value result{};+    if (ref_ != nullptr) {+      napi_get_reference_value(env_, ref_, &result);+    }+    return result;+  }++  explicit operator bool() const noexcept { return ref_ != nullptr; }++  friend void swap(RefHolder& left, RefHolder& right) noexcept {+    using std::swap;+    swap(left.env_, right.env_);+    swap(left.ref_, right.ref_);+  }++ private:+  napi_env env_{};+  napi_ref ref_{};+};

src/2-js-to-native-conversion/object-template-demo/napi/object-template-demo.cc

new file mode 100644@@ -0,0 +1,306 @@+#include <cstring>+#include <memory>+#include <string>+#include "proxy-template.h"++struct InstanceData {+  RefHolder constructor_;+  std::unique_ptr<ProxyTemplate> proxyTemplate_;+};++class NamedInterceptor {+  char buf[256];++ public:+  NamedInterceptor() { std::strncpy(this->buf, "foo", sizeof(this->buf)); }+  static napi_value Init(napi_env env, napi_value exports);+  static napi_value Constructor(napi_env env);+  static napi_value NewInstance(napi_env env);+  static napi_value New(napi_env env, napi_callback_info info);+  static napi_value CreateNew(napi_env env, napi_callback_info info);++  static napi_status ToUtf8String(napi_env env,+                                  napi_value value,+                                  std::string* result);+  static napi_status PropertyGetter(napi_env env,+                                    napi_value target,+                                    napi_value key,+                                    napi_value receiver,+                                    napi_value* result);+  static napi_status PropertySetter(napi_env env,+                                    napi_value target,+                                    napi_value key,+                                    napi_value value,+                                    napi_value receiver,+                                    bool* result);+  static napi_status PropertyDeleter(napi_env env,+                                     napi_value target,+                                     napi_value key,+                                     bool* result);+  static napi_status PropertyQuery(napi_env env,+                                   napi_value target,+                                   napi_value key,+                                   bool* result);+  static napi_status GetOwnPropertyDescriptor(napi_env env,+                                              napi_value target,+                                              napi_value key,+                                              napi_value* result);+  static napi_status OwnKeys(napi_env env,+                             napi_value target,+                             napi_value* result);+};++napi_value NamedInterceptor::CreateNew(napi_env env, napi_callback_info info) {+  return NamedInterceptor::NewInstance(env);+}++napi_value NamedInterceptor::Init(napi_env env, napi_value exports) {+  napi_value constructor{};+  NAPI_CALL(napi_define_class(env,+                              "NamedInterceptor",+                              NAPI_AUTO_LENGTH,+                              NamedInterceptor::New,+                              nullptr,+                              0,+                              nullptr,+                              &constructor));++  ProxyHandlerBuilder handlerBuilder{};+  NAPI_CALL(handlerBuilder.Get(env, &PropertyGetter));+  NAPI_CALL(handlerBuilder.Set(env, &PropertySetter));+  NAPI_CALL(handlerBuilder.DeleteProperty(env, &PropertyDeleter));+  NAPI_CALL(handlerBuilder.Has(env, &PropertyQuery));+  NAPI_CALL(+      handlerBuilder.GetOwnPropertyDescriptor(env, &GetOwnPropertyDescriptor));+  NAPI_CALL(handlerBuilder.OwnKeys(env, &OwnKeys));+  napi_value proxyHandler{};+  NAPI_CALL(handlerBuilder.NewHandler(env, &proxyHandler));+  NAPI_CALL(napi_set_instance_data(+      env,+      new InstanceData{RefHolder(env, constructor),+                       std::make_unique<ProxyTemplate>(env, proxyHandler)},+      [](napi_env /*env*/, void* data, void* /*hint*/) {+        delete static_cast<InstanceData*>(data);+      },+      nullptr));++  napi_value createFunc{};+  NAPI_CALL(napi_create_function(+      env, "create", NAPI_AUTO_LENGTH, CreateNew, nullptr, &createFunc));++  NAPI_CALL(napi_set_named_property(env, exports, "create", createFunc));+  return exports;+}++napi_value NamedInterceptor::Constructor(napi_env env) {+  InstanceData* instanceData{};+  NAPI_CALL(+      napi_get_instance_data(env, reinterpret_cast<void**>(&instanceData)));+  return instanceData->constructor_;+}++napi_value NamedInterceptor::NewInstance(napi_env env) {+  napi_escapable_handle_scope scope{};+  NAPI_CALL(napi_open_escapable_handle_scope(env, &scope));++  napi_value instance{};+  NAPI_CALL(napi_new_instance(env, Constructor(env), 0, nullptr, &instance));++  napi_value result{};+  NAPI_CALL(napi_escape_handle(env, scope, instance, &result));+  NAPI_CALL(napi_close_escapable_handle_scope(env, scope));+  return result;+}++napi_value NamedInterceptor::New(napi_env env, napi_callback_info info) {+  napi_value newTarget{};+  NAPI_CALL(napi_get_new_target(env, info, &newTarget));+  NODE_API_ASSERT_BASE(+      env, newTarget != nullptr, "Must be invoked as a constructor.", nullptr);++  napi_value proxyTarget{}, result{};+  NAPI_CALL(napi_create_function(+      env,+      "target",+      NAPI_AUTO_LENGTH,+      [](napi_env, napi_callback_info) -> napi_value { return nullptr; },+      nullptr,+      &proxyTarget));++  NamedInterceptor* obj = new NamedInterceptor();++  NAPI_CALL(napi_wrap(+      env,+      proxyTarget,+      obj,+      [](napi_env /*env*/, void* data, void* /*hint*/) {+        delete reinterpret_cast<NamedInterceptor*>(data);+      },+      nullptr,+      nullptr));++  InstanceData* instanceData{};+  NAPI_CALL(+      napi_get_instance_data(env, reinterpret_cast<void**>(&instanceData)));+  NAPI_CALL(+      instanceData->proxyTemplate_->NewInstance(env, proxyTarget, &result));+  return result;+}++napi_status NamedInterceptor::ToUtf8String(napi_env env,+                                           napi_value value,+                                           std::string* result) {+  size_t size{};+  CHECK_NAPI(napi_get_value_string_utf8(env, value, nullptr, 0, &size));+  result->assign(size, ' ');+  return napi_get_value_string_utf8(+      env, value, &(*result)[0], size + 1, nullptr);+}++napi_status NamedInterceptor::PropertyGetter(napi_env env,+                                             napi_value target,+                                             napi_value key,+                                             napi_value receiver,+                                             napi_value* result) {+  NamedInterceptor* interceptor{};+  CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));+  std::string keyStr;+  CHECK_NAPI(ToUtf8String(env, key, &keyStr));+  if (keyStr == "prop") {+    return napi_create_string_utf8(+        env, interceptor->buf, NAPI_AUTO_LENGTH, result);+  } else {+    return napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, result);+  }+}++napi_status NamedInterceptor::PropertySetter(napi_env env,+                                             napi_value target,+                                             napi_value key,+                                             napi_value value,+                                             napi_value receiver,+                                             bool* result) {+  NamedInterceptor* interceptor{};+  CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));+  std::string keyStr;+  CHECK_NAPI(ToUtf8String(env, key, &keyStr));+  if (keyStr == "prop") {+    std::string valueStr;+    CHECK_NAPI(ToUtf8String(env, value, &valueStr));+    std::strncpy(interceptor->buf, valueStr.data(), sizeof(interceptor->buf));+    *result = true;+  } else {+    *result = false;+  }+  return napi_ok;+}++napi_status NamedInterceptor::PropertyDeleter(napi_env env,+                                              napi_value target,+                                              napi_value key,+                                              bool* result) {+  NamedInterceptor* interceptor{};+  CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));+  std::strncpy(interceptor->buf, "goober", sizeof(interceptor->buf));+  *result = true;+  return napi_ok;+}++napi_status NamedInterceptor::PropertyQuery(napi_env env,+                                            napi_value target,+                                            napi_value key,+                                            bool* result) {+  std::string keyStr;+  CHECK_NAPI(ToUtf8String(env, key, &keyStr));++  if (keyStr == "thing") {+    *result = true;+  }+  if (keyStr == "value") {+    *result = true;+  }+  return napi_ok;+}++napi_status NamedInterceptor::GetOwnPropertyDescriptor(napi_env env,+                                                       napi_value target,+                                                       napi_value key,+                                                       napi_value* result) {+  std::string keyStr;+  CHECK_NAPI(ToUtf8String(env, key, &keyStr));++  if (keyStr == "thing") {+    CHECK_NAPI(napi_create_object(env, result));+    napi_value trueValue{};+    CHECK_NAPI(napi_get_boolean(env, true, &trueValue));+    CHECK_NAPI(+        napi_set_named_property(env, *result, "configurable", trueValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));+  }+  if (keyStr == "value") {+    CHECK_NAPI(napi_create_object(env, result));+    napi_value trueValue{};+    CHECK_NAPI(napi_get_boolean(env, true, &trueValue));+    CHECK_NAPI(+        napi_set_named_property(env, *result, "configurable", trueValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", trueValue));+  }+  if (keyStr == "arguments" || keyStr == "caller") {+    CHECK_NAPI(napi_create_object(env, result));+    napi_value trueValue{}, falseValue{};+    CHECK_NAPI(napi_get_boolean(env, false, &falseValue));+    CHECK_NAPI(napi_get_boolean(env, false, &trueValue));+    CHECK_NAPI(+        napi_set_named_property(env, *result, "configurable", falseValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "writable", falseValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", falseValue));+    napi_value nullValue{};+    CHECK_NAPI(napi_get_null(env, &nullValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "value", nullValue));+  }+  if (keyStr == "prototype") {+    CHECK_NAPI(napi_create_object(env, result));+    napi_value trueValue{}, falseValue{};+    CHECK_NAPI(napi_get_boolean(env, false, &falseValue));+    CHECK_NAPI(napi_get_boolean(env, true, &trueValue));+    CHECK_NAPI(+        napi_set_named_property(env, *result, "configurable", falseValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", falseValue));+    napi_value nullValue{};+    CHECK_NAPI(napi_get_null(env, &nullValue));+    CHECK_NAPI(napi_set_named_property(env, *result, "value", nullValue));+  }+  return napi_ok;+}++napi_status NamedInterceptor::OwnKeys(napi_env env,+                                      napi_value target,+                                      napi_value* result) {+  CHECK_NAPI(napi_get_all_property_names(env,+                                         target,+                                         napi_key_own_only,+                                         napi_key_all_properties,+                                         napi_key_keep_numbers,+                                         result));++  uint32_t arraySize{};+  CHECK_NAPI(napi_get_array_length(env, *result, &arraySize));+  napi_value firstElement{};+  CHECK_NAPI(napi_get_element(env, *result, 0, &firstElement));+  CHECK_NAPI(napi_set_element(env, *result, arraySize, firstElement));+  napi_value arraySizeValue{};+  CHECK_NAPI(napi_create_uint32(env, arraySize, &arraySizeValue));+  CHECK_NAPI(napi_set_named_property(env, *result, "length", arraySizeValue));+  napi_value value{};+  CHECK_NAPI(napi_create_string_utf8(env, "value", NAPI_AUTO_LENGTH, &value));+  CHECK_NAPI(napi_set_element(env, *result, 0, value));+  return napi_ok;+}++extern "C" napi_value Init(napi_env env, napi_value exports) {+  return NamedInterceptor::Init(env, exports);+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init);

src/2-js-to-native-conversion/object-template-demo/napi/package.json

new file mode 100644@@ -0,0 +1,14 @@+{+  "name": "object_template_demo",+  "version": "0.0.0",+  "description": "Intercept named property access using Proxy",+  "main": "index.js",+  "private": true,+  "gypfile": true,+  "scripts": {+    "test": "node index.js"+  },+  "dependencies": {+    "bindings": "~1.5.0"+  }+}

src/2-js-to-native-conversion/object-template-demo/napi/proxy-template.cc

new file mode 100644@@ -0,0 +1,726 @@+#include "proxy-template.h"+#include <vector>++namespace {++static napi_status SetTrap(napi_env env,+                           napi_value handler,+                           const char* propertyName,+                           napi_value trap) noexcept {+  if (trap != nullptr) {+    CHECK_NAPI(napi_set_named_property(env, handler, propertyName, trap));+  }+  return napi_ok;+}++using TrapCaller = napi_status (*)(napi_env env,+                                   void* trap,+                                   napi_span<napi_value> args,+                                   napi_value* result);++struct TrapCallInfo {+  TrapCaller Caller;+  void* trap;+};++template <size_t argCount>+napi_callback CreateTrapCallback() noexcept {+  return [](napi_env env, napi_callback_info info) noexcept -> napi_value {+    TrapCallInfo* trapCallInfo{};+    napi_value args[argCount]{};+    size_t actualArgCount{argCount};+    NAPI_CALL(napi_get_cb_info(env,+                               info,+                               &actualArgCount,+                               args,+                               nullptr,+                               reinterpret_cast<void**>(&trapCallInfo)));+    NODE_API_ASSERT_BASE(env,+                         actualArgCount == argCount,+                         "proxy trap requires argCount arguments.",+                         nullptr);+    napi_value result{};+    NAPI_CALL(trapCallInfo->Caller(+        env, trapCallInfo->trap, span<napi_value>(args, argCount), &result));+    return result;+  };+}++napi_status ToVector(napi_env env,+                     napi_value arrayValue,+                     std::vector<napi_value>* result) {+  bool isArray{};+  CHECK_NAPI(napi_is_array(env, arrayValue, &isArray));+  if (isArray) {+    uint32_t arraySize{};+    CHECK_NAPI(napi_get_array_length(env, arrayValue, &arraySize));+    result->reserve(result->size() + arraySize);+    for (uint32_t i = 0; i < arraySize; ++i) {+      napi_value arrayElement{};+      CHECK_NAPI(napi_get_element(env, arrayValue, i, &arrayElement));+      result->push_back(arrayElement);+    }+  }+  return napi_ok;+}++}  // namespace++napi_status ProxyHandlerBuilder::NewHandler(napi_env env,+                                            napi_value* result) noexcept {+  CHECK_NAPI(napi_create_object(env, result));++  CHECK_NAPI(SetTrap(env, *result, "apply", apply_));+  CHECK_NAPI(SetTrap(env, *result, "construct", construct_));+  CHECK_NAPI(SetTrap(env, *result, "defineProperty", defineProperty_));+  CHECK_NAPI(SetTrap(env, *result, "deleteProperty", deleteProperty_));+  CHECK_NAPI(SetTrap(env, *result, "get", get_));+  CHECK_NAPI(SetTrap(+      env, *result, "getOwnPropertyDescriptor", getOwnPropertyDescriptor_));+  CHECK_NAPI(SetTrap(env, *result, "getPrototypeOf", getPrototypeOf_));+  CHECK_NAPI(SetTrap(env, *result, "has", has_));+  CHECK_NAPI(SetTrap(env, *result, "isExtensible", isExtensible_));+  CHECK_NAPI(SetTrap(env, *result, "ownKeys", ownKeys_));+  CHECK_NAPI(SetTrap(env, *result, "preventExtensions", preventExtensions_));+  CHECK_NAPI(SetTrap(env, *result, "set", set_));+  CHECK_NAPI(SetTrap(env, *result, "setPrototypeOf", setPrototypeOf_));+  return napi_ok;+}++napi_value ProxyHandlerBuilder::Apply() noexcept {+  return apply_;+}++void ProxyHandlerBuilder::Apply(napi_value trap) noexcept {+  apply_ = trap;+}++napi_status ProxyHandlerBuilder::Apply(napi_env env,+                                       napi_callback trap,+                                       void* data) noexcept {+  return napi_create_function(+      env, "apply", NAPI_AUTO_LENGTH, trap, data, &apply_);+}++napi_status ProxyHandlerBuilder::Apply(+    napi_env env,+    napi_status (*trap)(napi_env env,+                        napi_value target,+                        napi_value thisArg,+                        napi_value argumentList,+                        napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], args[2], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return Apply(env, CreateTrapCallback<3>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Apply(+    napi_env env,+    napi_status (*trap)(napi_env env,+                        napi_value target,+                        napi_value thisArg,+                        napi_span<napi_value> argumentList,+                        napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{+      [](napi_env env,+         void* trap,+         napi_span<napi_value> args,+         napi_value* result) noexcept {+        std::vector<napi_value> argVector;+        CHECK_NAPI(ToVector(env, args[2], &argVector));+        return reinterpret_cast<TrapType>(trap)(+            env,+            args[0],+            args[1],+            span<napi_value>(argVector.data(), argVector.size()),+            result);+      },+      reinterpret_cast<void*>(trap)};+  return Apply(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Construct() noexcept {+  return construct_;+}++void ProxyHandlerBuilder::Construct(napi_value trap) noexcept {+  construct_ = trap;+}++napi_status ProxyHandlerBuilder::Construct(napi_env env,+                                           napi_callback trap,+                                           void* data) noexcept {+  return napi_create_function(+      env, "construct", NAPI_AUTO_LENGTH, trap, data, &construct_);+}++napi_status ProxyHandlerBuilder::Construct(+    napi_env env,+    napi_status (*trap)(napi_env env,+                        napi_value target,+                        napi_value argumentList,+                        napi_value newTarget,+                        napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], args[2], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return Construct(env, CreateTrapCallback<3>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Construct(+    napi_env env,+    napi_status (*trap)(napi_env env,+                        napi_value target,+                        napi_span<napi_value> argumentList,+                        napi_value newTarget,+                        napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{+      [](napi_env env,+         void* trap,+         napi_span<napi_value> args,+         napi_value* result) noexcept {+        std::vector<napi_value> argVector;+        CHECK_NAPI(ToVector(env, args[1], &argVector));+        return reinterpret_cast<TrapType>(trap)(+            env,+            args[0],+            span<napi_value>(argVector.data(), argVector.size()),+            args[2],+            result);+      },+      reinterpret_cast<void*>(trap)};+  return Construct(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::DefineProperty() noexcept {+  return defineProperty_;+}++void ProxyHandlerBuilder::DefineProperty(napi_value trap) noexcept {+  defineProperty_ = trap;+}++napi_status ProxyHandlerBuilder::DefineProperty(napi_env env,+                                                napi_callback trap,+                                                void* data) noexcept {+  return napi_create_function(+      env, "defineProperty", NAPI_AUTO_LENGTH, trap, data, &defineProperty_);+}++napi_status ProxyHandlerBuilder::DefineProperty(+    napi_env env,+    napi_status (*trap)(napi_env env,+                        napi_value target,+                        napi_value key,+                        napi_value descriptor,+                        napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], args[2], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return DefineProperty(env, CreateTrapCallback<3>(), &callInfo);+}++napi_status ProxyHandlerBuilder::DefineProperty(+    napi_env env,+    napi_status (*trap)(napi_env env,+                        napi_value target,+                        napi_value key,+                        napi_value descriptor,+                        bool* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{+      [](napi_env env,+         void* trap,+         napi_span<napi_value> args,+         napi_value* result) noexcept {+        bool boolResult{};+        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+            env, args[0], args[1], args[2], &boolResult));+        return napi_get_boolean(env, boolResult, result);+      },+      reinterpret_cast<void*>(trap)};+  return DefineProperty(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::DeleteProperty() noexcept {+  return deleteProperty_;+}++void ProxyHandlerBuilder::DeleteProperty(napi_value trap) noexcept {+  deleteProperty_ = trap;+}++napi_status ProxyHandlerBuilder::DeleteProperty(napi_env env,+                                                napi_callback trap,+                                                void* data) noexcept {+  return napi_create_function(+      env, "deleteProperty", NAPI_AUTO_LENGTH, trap, data, &deleteProperty_);+}++napi_status ProxyHandlerBuilder::DeleteProperty(+    napi_env env,+    napi_status (*trap)(+        napi_env env, napi_value target, napi_value key, napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return DeleteProperty(env, CreateTrapCallback<2>(), &callInfo);+}++napi_status ProxyHandlerBuilder::DeleteProperty(+    napi_env env,+    napi_status (*trap)(+        napi_env env, napi_value target, napi_value key, bool* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 bool boolResult{};+                                 CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], &boolResult));+                                 return napi_get_boolean(+                                     env, boolResult, result);+                               },+                               reinterpret_cast<void*>(trap)};+  return DeleteProperty(env, CreateTrapCallback<2>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Get() noexcept {+  return get_;+}++void ProxyHandlerBuilder::Get(napi_value trap) noexcept {+  get_ = trap;+}++napi_status ProxyHandlerBuilder::Get(napi_env env,+                                     napi_callback trap,+                                     void* data) noexcept {+  return napi_create_function(env, "get", NAPI_AUTO_LENGTH, trap, data, &get_);+}++napi_status ProxyHandlerBuilder::Get(napi_env env,+                                     napi_status (*trap)(napi_env env,+                                                         napi_value target,+                                                         napi_value key,+                                                         napi_value receiver,+                                                         napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], args[2], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return Get(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::GetOwnPropertyDescriptor() noexcept {+  return getOwnPropertyDescriptor_;+}++void ProxyHandlerBuilder::GetOwnPropertyDescriptor(napi_value trap) noexcept {+  getOwnPropertyDescriptor_ = trap;+}++napi_status ProxyHandlerBuilder::GetOwnPropertyDescriptor(napi_env env,+                                                          napi_callback trap,+                                                          void* data) noexcept {+  return napi_create_function(env,+                              "getOwnPropertyDescriptor",+                              NAPI_AUTO_LENGTH,+                              trap,+                              data,+                              &getOwnPropertyDescriptor_);+}++napi_status ProxyHandlerBuilder::GetOwnPropertyDescriptor(+    napi_env env,+    napi_status (*trap)(+        napi_env env, napi_value target, napi_value key, napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return GetOwnPropertyDescriptor(env, CreateTrapCallback<2>(), &callInfo);+}++napi_value ProxyHandlerBuilder::GetPrototypeOf() noexcept {+  return getPrototypeOf_;+}++void ProxyHandlerBuilder::GetPrototypeOf(napi_value trap) noexcept {+  getPrototypeOf_ = trap;+}++napi_status ProxyHandlerBuilder::GetPrototypeOf(napi_env env,+                                                napi_callback trap,+                                                void* data) noexcept {+  return napi_create_function(+      env, "getPrototypeOf", NAPI_AUTO_LENGTH, trap, data, &getPrototypeOf_);+}++napi_status ProxyHandlerBuilder::GetPrototypeOf(+    napi_env env,+    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return GetPrototypeOf(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Has() noexcept {+  return has_;+}++void ProxyHandlerBuilder::Has(napi_value trap) noexcept {+  has_ = trap;+}++napi_status ProxyHandlerBuilder::Has(napi_env env,+                                     napi_callback trap,+                                     void* data) noexcept {+  return napi_create_function(env, "has", NAPI_AUTO_LENGTH, trap, data, &has_);+}++napi_status ProxyHandlerBuilder::Has(napi_env env,+                                     napi_status (*trap)(napi_env env,+                                                         napi_value target,+                                                         napi_value key,+                                                         napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return Has(env, CreateTrapCallback<2>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Has(napi_env env,+                                     napi_status (*trap)(napi_env env,+                                                         napi_value target,+                                                         napi_value key,+                                                         bool* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 bool boolResult{};+                                 CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], &boolResult));+                                 return napi_get_boolean(+                                     env, boolResult, result);+                               },+                               reinterpret_cast<void*>(trap)};+  return Has(env, CreateTrapCallback<2>(), &callInfo);+}++napi_value ProxyHandlerBuilder::IsExtensible() noexcept {+  return isExtensible_;+}++void ProxyHandlerBuilder::IsExtensible(napi_value trap) noexcept {+  isExtensible_ = trap;+}++napi_status ProxyHandlerBuilder::IsExtensible(napi_env env,+                                              napi_callback trap,+                                              void* data) noexcept {+  return napi_create_function(+      env, "isExtensible", NAPI_AUTO_LENGTH, trap, data, &isExtensible_);+}++napi_status ProxyHandlerBuilder::IsExtensible(+    napi_env env,+    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return IsExtensible(env, CreateTrapCallback<1>(), &callInfo);+}++napi_status ProxyHandlerBuilder::IsExtensible(+    napi_env env,+    napi_status (*trap)(napi_env env, napi_value target, bool* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{+      [](napi_env env,+         void* trap,+         napi_span<napi_value> args,+         napi_value* result) noexcept {+        bool boolResult{};+        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(env, args[0], &boolResult));+        return napi_get_boolean(env, boolResult, result);+      },+      reinterpret_cast<void*>(trap)};+  return IsExtensible(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::OwnKeys() noexcept {+  return ownKeys_;+}++void ProxyHandlerBuilder::OwnKeys(napi_value trap) noexcept {+  ownKeys_ = trap;+}++napi_status ProxyHandlerBuilder::OwnKeys(napi_env env,+                                         napi_callback trap,+                                         void* data) noexcept {+  return napi_create_function(+      env, "ownKeys", NAPI_AUTO_LENGTH, trap, data, &ownKeys_);+}++napi_status ProxyHandlerBuilder::OwnKeys(+    napi_env env,+    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return OwnKeys(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::PreventExtensions() noexcept {+  return preventExtensions_;+}++void ProxyHandlerBuilder::PreventExtensions(napi_value trap) noexcept {+  preventExtensions_ = trap;+}++napi_status ProxyHandlerBuilder::PreventExtensions(napi_env env,+                                                   napi_callback trap,+                                                   void* data) noexcept {+  return napi_create_function(env,+                              "preventExtensions",+                              NAPI_AUTO_LENGTH,+                              trap,+                              data,+                              &preventExtensions_);+}++napi_status ProxyHandlerBuilder::PreventExtensions(+    napi_env env,+    napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return PreventExtensions(env, CreateTrapCallback<1>(), &callInfo);+}++napi_status ProxyHandlerBuilder::PreventExtensions(+    napi_env env,+    napi_status (*trap)(napi_env env, napi_value target, bool* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{+      [](napi_env env,+         void* trap,+         napi_span<napi_value> args,+         napi_value* result) noexcept {+        bool boolResult{};+        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(env, args[0], &boolResult));+        return napi_get_boolean(env, boolResult, result);+      },+      reinterpret_cast<void*>(trap)};+  return PreventExtensions(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Set() noexcept {+  return set_;+}++void ProxyHandlerBuilder::Set(napi_value trap) noexcept {+  set_ = trap;+}++napi_status ProxyHandlerBuilder::Set(napi_env env,+                                     napi_callback trap,+                                     void* data) noexcept {+  return napi_create_function(env, "set", NAPI_AUTO_LENGTH, trap, data, &set_);+}++napi_status ProxyHandlerBuilder::Set(napi_env env,+                                     napi_status (*trap)(napi_env env,+                                                         napi_value target,+                                                         napi_value key,+                                                         napi_value value,+                                                         napi_value receiver,+                                                         napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{+      [](napi_env env,+         void* trap,+         napi_span<napi_value> args,+         napi_value* result) noexcept {+        return reinterpret_cast<TrapType>(trap)(+            env, args[0], args[1], args[2], args[3], result);+      },+      reinterpret_cast<void*>(trap)};+  return Set(env, CreateTrapCallback<4>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Set(napi_env env,+                                     napi_status (*trap)(napi_env env,+                                                         napi_value target,+                                                         napi_value key,+                                                         napi_value value,+                                                         napi_value receiver,+                                                         bool* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{+      [](napi_env env,+         void* trap,+         napi_span<napi_value> args,+         napi_value* result) noexcept {+        bool boolResult{};+        CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+            env, args[0], args[1], args[2], args[3], &boolResult));+        return napi_get_boolean(env, boolResult, result);+      },+      reinterpret_cast<void*>(trap)};+  return Set(env, CreateTrapCallback<4>(), &callInfo);+}++napi_value ProxyHandlerBuilder::SetPrototypeOf() noexcept {+  return setPrototypeOf_;+}++void ProxyHandlerBuilder::SetPrototypeOf(napi_value trap) noexcept {+  setPrototypeOf_ = trap;+}++napi_status ProxyHandlerBuilder::SetPrototypeOf(napi_env env,+                                                napi_callback trap,+                                                void* data) noexcept {+  return napi_create_function(+      env, "setPrototypeOf", NAPI_AUTO_LENGTH, trap, data, &setPrototypeOf_);+}++napi_status ProxyHandlerBuilder::SetPrototypeOf(+    napi_env env,+    napi_status (*trap)(napi_env env,+                        napi_value target,+                        napi_value prototype,+                        napi_value* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 return reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], result);+                               },+                               reinterpret_cast<void*>(trap)};+  return SetPrototypeOf(env, CreateTrapCallback<2>(), &callInfo);+}++napi_status ProxyHandlerBuilder::SetPrototypeOf(+    napi_env env,+    napi_status (*trap)(+        napi_env env, napi_value target, napi_value prototype, bool* result)) {+  using TrapType = decltype(trap);+  static TrapCallInfo callInfo{[](napi_env env,+                                  void* trap,+                                  napi_span<napi_value> args,+                                  napi_value* result) noexcept {+                                 bool boolResult{};+                                 CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+                                     env, args[0], args[1], &boolResult));+                                 return napi_get_boolean(+                                     env, boolResult, result);+                               },+                               reinterpret_cast<void*>(trap)};+  return SetPrototypeOf(env, CreateTrapCallback<2>(), &callInfo);+}++//=============++ProxyTemplate::ProxyTemplate(napi_env env, napi_value proxyHandler) noexcept+    : proxyHandler_(RefHolder(env, proxyHandler)) {}++napi_status ProxyTemplate::NewInstance(napi_env env,+                                       napi_value target,+                                       napi_value* result) noexcept {+  napi_value proxyConstructor{};+  CHECK_NAPI(GetProxyConstructor(env, &proxyConstructor));++  napi_value args[] = {target, static_cast<napi_value>(proxyHandler_)};+  return napi_new_instance(env, proxyConstructor, 2, args, result);+}++napi_status ProxyTemplate::GetProxyConstructor(napi_env env,+                                               napi_value* result) noexcept {+  if (!proxyConstructor_) {+    napi_value global{}, proxyConstructor{};+    CHECK_NAPI(napi_get_global(env, &global));+    CHECK_NAPI(+        napi_get_named_property(env, global, "Proxy", &proxyConstructor));+    proxyConstructor_ = RefHolder(env, proxyConstructor);+  }+  *result = proxyConstructor_;+  return napi_ok;+}

src/2-js-to-native-conversion/object-template-demo/napi/proxy-template.h

new file mode 100644@@ -0,0 +1,249 @@+#include "node-api-common.h"++template <typename T>+using napi_span = span<T>;++// Creates a handler object for a JavaScript Proxy.+// See+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy+// for details about JavaScript Proxy.+//+// There are four different ways we can set each Proxy handler trap:+// - using napi_value function.+// - using napi_callback that creates function.+// - using a callback signature that matches Proxy handler definition arguments.+// - using a callback based on the Proxy handler trap signature where we replace+//   napi_value with strongly typed values such as bool or+//   napi_span<napi_value>.+//+// Note that ProxyHandlerBuilder keeps handler trap functions as napi_value+// and thus cannot be persisted. The typical usage is to create new+// ProxyHandlerBuilder instance on the call stack, set handler traps, create+// handler to pass to Proxy constructor or ProxyTemplate, and not to reuse the+// ProxyHandlerBuilder instance.+struct ProxyHandlerBuilder {+  napi_status NewHandler(napi_env env, napi_value* result) noexcept;++  napi_value Apply() noexcept;+  void Apply(napi_value trap) noexcept;+  napi_status Apply(napi_env env,+                    napi_callback trap,+                    void* data = nullptr) noexcept;+  napi_status Apply(napi_env env,+                    napi_status (*trap)(napi_env env,+                                        napi_value target,+                                        napi_value thisArg,+                                        napi_value argumentList,+                                        napi_value* result));+  napi_status Apply(napi_env env,+                    napi_status (*trap)(napi_env env,+                                        napi_value target,+                                        napi_value thisArg,+                                        napi_span<napi_value> argumentList,+                                        napi_value* result));++  napi_value Construct() noexcept;+  void Construct(napi_value trap) noexcept;+  napi_status Construct(napi_env env,+                        napi_callback trap,+                        void* data = nullptr) noexcept;+  napi_status Construct(napi_env env,+                        napi_status (*trap)(napi_env env,+                                            napi_value target,+                                            napi_value argumentList,+                                            napi_value newTarget,+                                            napi_value* result));+  napi_status Construct(napi_env env,+                        napi_status (*trap)(napi_env env,+                                            napi_value target,+                                            napi_span<napi_value> argumentList,+                                            napi_value newTarget,+                                            napi_value* result));++  napi_value DefineProperty() noexcept;+  void DefineProperty(napi_value trap) noexcept;+  napi_status DefineProperty(napi_env env,+                             napi_callback trap,+                             void* data = nullptr) noexcept;+  napi_status DefineProperty(napi_env env,+                             napi_status (*trap)(napi_env env,+                                                 napi_value target,+                                                 napi_value key,+                                                 napi_value descriptor,+                                                 napi_value* result));+  napi_status DefineProperty(napi_env env,+                             napi_status (*trap)(napi_env env,+                                                 napi_value target,+                                                 napi_value key,+                                                 napi_value descriptor,+                                                 bool* result));++  napi_value DeleteProperty() noexcept;+  void DeleteProperty(napi_value trap) noexcept;+  napi_status DeleteProperty(napi_env env,+                             napi_callback trap,+                             void* data = nullptr) noexcept;+  napi_status DeleteProperty(napi_env env,+                             napi_status (*trap)(napi_env env,+                                                 napi_value target,+                                                 napi_value key,+                                                 napi_value* result));+  napi_status DeleteProperty(napi_env env,+                             napi_status (*trap)(napi_env env,+                                                 napi_value target,+                                                 napi_value key,+                                                 bool* result));++  napi_value Get() noexcept;+  void Get(napi_value trap) noexcept;+  napi_status Get(napi_env env,+                  napi_callback trap,+                  void* data = nullptr) noexcept;+  napi_status Get(napi_env env,+                  napi_status (*trap)(napi_env env,+                                      napi_value target,+                                      napi_value key,+                                      napi_value receiver,+                                      napi_value* result));++  napi_value GetOwnPropertyDescriptor() noexcept;+  void GetOwnPropertyDescriptor(napi_value trap) noexcept;+  napi_status GetOwnPropertyDescriptor(napi_env env,+                                       napi_callback trap,+                                       void* data = nullptr) noexcept;+  napi_status GetOwnPropertyDescriptor(napi_env env,+                                       napi_status (*trap)(napi_env env,+                                                           napi_value target,+                                                           napi_value key,+                                                           napi_value* result));++  napi_value GetPrototypeOf() noexcept;+  void GetPrototypeOf(napi_value trap) noexcept;+  napi_status GetPrototypeOf(napi_env env,+                             napi_callback trap,+                             void* data = nullptr) noexcept;+  napi_status GetPrototypeOf(napi_env env,+                             napi_status (*trap)(napi_env env,+                                                 napi_value target,+                                                 napi_value* result));++  napi_value Has() noexcept;+  void Has(napi_value trap) noexcept;+  napi_status Has(napi_env env,+                  napi_callback trap,+                  void* data = nullptr) noexcept;+  napi_status Has(napi_env env,+                  napi_status (*trap)(napi_env env,+                                      napi_value target,+                                      napi_value key,+                                      napi_value* result));+  napi_status Has(napi_env env,+                  napi_status (*trap)(napi_env env,+                                      napi_value target,+                                      napi_value key,+                                      bool* result));++  napi_value IsExtensible() noexcept;+  void IsExtensible(napi_value trap) noexcept;+  napi_status IsExtensible(napi_env env,+                           napi_callback trap,+                           void* data = nullptr) noexcept;+  napi_status IsExtensible(napi_env env,+                           napi_status (*trap)(napi_env env,+                                               napi_value target,+                                               napi_value* result));+  napi_status IsExtensible(napi_env env,+                           napi_status (*trap)(napi_env env,+                                               napi_value target,+                                               bool* result));++  napi_value OwnKeys() noexcept;+  void OwnKeys(napi_value trap) noexcept;+  napi_status OwnKeys(napi_env env,+                      napi_callback trap,+                      void* data = nullptr) noexcept;+  napi_status OwnKeys(napi_env env,+                      napi_status (*trap)(napi_env env,+                                          napi_value target,+                                          napi_value* result));++  napi_value PreventExtensions() noexcept;+  void PreventExtensions(napi_value trap) noexcept;+  napi_status PreventExtensions(napi_env env,+                                napi_callback trap,+                                void* data = nullptr) noexcept;+  napi_status PreventExtensions(napi_env env,+                                napi_status (*trap)(napi_env env,+                                                    napi_value target,+                                                    napi_value* result));+  napi_status PreventExtensions(napi_env env,+                                napi_status (*trap)(napi_env env,+                                                    napi_value target,+                                                    bool* result));++  napi_value Set() noexcept;+  void Set(napi_value trap) noexcept;+  napi_status Set(napi_env env,+                  napi_callback trap,+                  void* data = nullptr) noexcept;+  napi_status Set(napi_env env,+                  napi_status (*trap)(napi_env env,+                                      napi_value target,+                                      napi_value key,+                                      napi_value value,+                                      napi_value receiver,+                                      napi_value* result));+  napi_status Set(napi_env env,+                  napi_status (*trap)(napi_env env,+                                      napi_value target,+                                      napi_value key,+                                      napi_value value,+                                      napi_value receiver,+                                      bool* result));++  napi_value SetPrototypeOf() noexcept;+  void SetPrototypeOf(napi_value trap) noexcept;+  napi_status SetPrototypeOf(napi_env env,+                             napi_callback trap,+                             void* data = nullptr) noexcept;+  napi_status SetPrototypeOf(napi_env env,+                             napi_status (*trap)(napi_env env,+                                                 napi_value target,+                                                 napi_value prototype,+                                                 napi_value* result));+  napi_status SetPrototypeOf(napi_env env,+                             napi_status (*trap)(napi_env env,+                                                 napi_value target,+                                                 napi_value prototype,+                                                 bool* result));++ private:+  napi_value apply_{};+  napi_value construct_{};+  napi_value defineProperty_{};+  napi_value deleteProperty_{};+  napi_value get_{};+  napi_value getOwnPropertyDescriptor_{};+  napi_value getPrototypeOf_{};+  napi_value has_{};+  napi_value isExtensible_{};+  napi_value ownKeys_{};+  napi_value preventExtensions_{};+  napi_value set_{};+  napi_value setPrototypeOf_{};+};++struct ProxyTemplate {+  ProxyTemplate(napi_env env, napi_value proxyHandler) noexcept;++  napi_status NewInstance(napi_env env,+                          napi_value target,+                          napi_value* result) noexcept;++ private:+  napi_status GetProxyConstructor(napi_env env, napi_value* result) noexcept;++ private:+  RefHolder proxyConstructor_{};+  RefHolder proxyHandler_{};+};

src/2-js-to-native-conversion/object-wrap-demo/node-addon-api/README.md

new file mode 100644@@ -0,0 +1,14 @@+# Node-API Object Wrap Demo++This is an example project that accompanies the Node-API workshop tutorials++A tutorial describing this project can be found at the [Node-API Resource](https://napi.inspiredware.com/getting-started/objectwrap.html).++To build and run this program on your system, clone it to your computer and run these two commands inside your clone:++```+npm install+npm test+```++> You need to have Node 10.5.0 or later installed. \ No newline at end of file

src/2-js-to-native-conversion/object-wrap-demo/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,20 @@+{+  'targets': [+    {+      'target_name': 'object-wrap-demo-native',+      'sources': [ 'src/object_wrap_demo.cc' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'xcode_settings': {+        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+        'CLANG_CXX_LIBRARY': 'libc++',+        'MACOSX_DEPLOYMENT_TARGET': '10.7'+      },+      'msvs_settings': {+        'VCCLCompilerTool': { 'ExceptionHandling': 1 },+      }+    }+  ]+}\ No newline at end of file

src/2-js-to-native-conversion/object-wrap-demo/node-addon-api/lib/binding.js

new file mode 100644@@ -0,0 +1,11 @@+const addon = require('../build/Release/object-wrap-demo-native');++function ObjectWrapDemo(name) {+    this.greet = function(str) {+        return _addonInstance.greet(str);+    }++    var _addonInstance = new addon.ObjectWrapDemo(name);+}++module.exports = ObjectWrapDemo;

src/2-js-to-native-conversion/object-wrap-demo/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,16 @@+{+  "main": "lib/binding.js",+  "private": true,+  "dependencies": {+    "node-addon-api": "^1.1.0"+  },+  "scripts": {+    "test": "node --napi-modules ./test/test_binding.js"+  },+  "gypfile": true,+  "name": "object-wrap-demo",+  "version": "1.0.0",+  "description": "An object wrapper demo",+  "author": "Your name goes here",+  "license": "MIT"+}

src/2-js-to-native-conversion/object-wrap-demo/node-addon-api/src/object_wrap_demo.cc

new file mode 100644@@ -0,0 +1,62 @@+#include "object_wrap_demo.h"++using namespace Napi;++ObjectWrapDemo::ObjectWrapDemo(const Napi::CallbackInfo& info)+    : ObjectWrap(info) {+  Napi::Env env = info.Env();++  if (info.Length() < 1) {+    Napi::TypeError::New(env, "Wrong number of arguments")+        .ThrowAsJavaScriptException();+    return;+  }++  if (!info[0].IsString()) {+    Napi::TypeError::New(env, "You need to name yourself")+        .ThrowAsJavaScriptException();+    return;+  }++  this->_greeterName = info[0].As<Napi::String>().Utf8Value();+}++Napi::Value ObjectWrapDemo::Greet(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();++  if (info.Length() < 1) {+    Napi::TypeError::New(env, "Wrong number of arguments")+        .ThrowAsJavaScriptException();+    return env.Null();+  }++  if (!info[0].IsString()) {+    Napi::TypeError::New(env, "You need to introduce yourself to greet")+        .ThrowAsJavaScriptException();+    return env.Null();+  }++  Napi::String name = info[0].As<Napi::String>();++  printf("Hello %s\n", name.Utf8Value().c_str());+  printf("I am %s\n", this->_greeterName.c_str());++  return Napi::String::New(env, this->_greeterName);+}++Napi::Function ObjectWrapDemo::GetClass(Napi::Env env) {+  return DefineClass(+      env,+      "ObjectWrapDemo",+      {+          ObjectWrapDemo::InstanceMethod("greet", &ObjectWrapDemo::Greet),+      });+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  Napi::String name = Napi::String::New(env, "ObjectWrapDemo");+  exports.Set(name, ObjectWrapDemo::GetClass(env));+  return exports;+}++NODE_API_MODULE(addon, Init)

src/2-js-to-native-conversion/object-wrap-demo/node-addon-api/src/object_wrap_demo.h

new file mode 100644@@ -0,0 +1,14 @@+#pragma once++#include <napi.h>++class ObjectWrapDemo : public Napi::ObjectWrap<ObjectWrapDemo> {+ public:+  ObjectWrapDemo(const Napi::CallbackInfo&);+  Napi::Value Greet(const Napi::CallbackInfo&);++  static Napi::Function GetClass(Napi::Env);++ private:+  std::string _greeterName;+};

src/2-js-to-native-conversion/object-wrap-demo/node-addon-api/test/test_binding.js

new file mode 100644@@ -0,0 +1,21 @@+const ObjectWrapDemo = require("../lib/binding.js");+const assert = require("assert");++assert(ObjectWrapDemo, "The expected module is undefined");++function testBasic()+{+    const instance = new ObjectWrapDemo("mr-yeoman");+    assert(instance.greet, "The expected method is not defined");+    assert.strictEqual(instance.greet("kermit"), "mr-yeoman", "Unexpected value returned");+}++function testInvalidParams()+{+    const instance = new ObjectWrapDemo();+}++assert.doesNotThrow(testBasic, undefined, "testBasic threw an expection");+assert.throws(testInvalidParams, undefined, "testInvalidParams didn't throw");++console.log("Tests passed- everything looks OK!");\ No newline at end of file

src/2-js-to-native-conversion/typed_array_to_native/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "typed_array_to_native",+      "cflags!": [ "-fno-exceptions" ],+      "cflags_cc!": [ "-fno-exceptions" ],+      "sources": [ "typed_array_to_native.cc" ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],+    }+  ]+}

src/2-js-to-native-conversion/typed_array_to_native/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,15 @@+const binding = require('bindings')('typed_array_to_native');++{+    const byteArray = Uint8Array.from([10, 20, 30, 50, 25, 17]);+    console.log("byteArray: ", byteArray);+    binding.AcceptByteArray(byteArray);+}+console.log("---------");++{+    const array = [7, 15, 26, 58, 64];+    console.log("array: ", array);+    const byteArray = binding.CreateByteArray(array);+    console.log("byteArray: ", byteArray);+}\ No newline at end of file

src/2-js-to-native-conversion/typed_array_to_native/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,14 @@+{+  "name": "typed_array_to_native",+  "version": "0.0.0",+  "description": "Shows how to read and create typed arrays",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "node-addon-api": "^1.0.0"+  },+  "scripts": {+    "test": "node index.js"+  }+}

src/2-js-to-native-conversion/typed_array_to_native/node-addon-api/typed_array_to_native.cc

new file mode 100644@@ -0,0 +1,109 @@+#include <napi.h>+#include <cstdio>++static Napi::Value AcceptByteArray(const Napi::CallbackInfo& info) {+  if (info.Length() != 1) {+    Napi::Error::New(info.Env(), "Expected exactly one argument")+        .ThrowAsJavaScriptException();+    return info.Env().Undefined();+  }++  if (!info[0].IsTypedArray()) {+    Napi::Error::New(info.Env(), "Expected a TypedArray")+        .ThrowAsJavaScriptException();+    return info.Env().Undefined();+  }+  Napi::TypedArray typedArray = info[0].As<Napi::TypedArray>();++  if (typedArray.TypedArrayType() != napi_uint8_array) {+    Napi::Error::New(info.Env(), "Expected an Uint8Array")+        .ThrowAsJavaScriptException();+    return info.Env().Undefined();+  }+  Napi::Uint8Array uint8Array = typedArray.As<Napi::Uint8Array>();++  // Copy to std::vector<uint8_t>:+  std::vector<uint8_t> bytes(uint8Array.Data(),+                             uint8Array.Data() + uint8Array.ElementLength());+  printf("std::vector<uint8_t> from Uint8Array: [");+  for (uint8_t byte : bytes) {+    printf("%d, ", byte);+  }+  printf("\b\b]\n");++  return info.Env().Undefined();+}++static Napi::Value CreateByteArray(const Napi::CallbackInfo& info) {+  if (info.Length() != 1) {+    Napi::Error::New(info.Env(), "Expected exactly one argument")+        .ThrowAsJavaScriptException();+    return info.Env().Undefined();+  }++  if (!info[0].IsArray()) {+    Napi::Error::New(info.Env(), "Expected an Array")+        .ThrowAsJavaScriptException();+    return info.Env().Undefined();+  }+  Napi::Array array = info[0].As<Napi::Array>();+  size_t arrayLength = array.Length();++  // Create std::vector<uint8_t> out of array.+  // We allocate it on the heap to allow wrapping it up into ArrayBuffer.+  std::unique_ptr<std::vector<uint8_t>> nativeArray =+      std::make_unique<std::vector<uint8_t>>(arrayLength, 0);+  for (size_t i = 0; i < arrayLength; ++i) {+    Napi::Value arrayItem = array[i];+    if (!arrayItem.IsNumber()) {+      Napi::Error::New(info.Env(), "Expected a Number as Array Item")+          .ThrowAsJavaScriptException();+      return info.Env().Undefined();+    }+    Napi::Number number = arrayItem.As<Napi::Number>();+    double numberValue = number.DoubleValue();+    if (numberValue < 0 || numberValue > 255) {+      Napi::Error::New(info.Env(),+                       "Array Item Number value is out of range [0..255]")+          .ThrowAsJavaScriptException();+      return info.Env().Undefined();+    }++    (*nativeArray)[i] = static_cast<uint8_t>(numberValue);+  }++  printf("std::vector<uint8_t> from Array: [");+  for (uint8_t byte : *nativeArray) {+    printf("%d, ", byte);+  }+  printf("\b\b]\n");++  // Wrap up the std::vector into the ArrayBuffer.+  // Note: instead of wrapping the std::vector we could allow ArrayBuffer to+  // create internal storage that copies the std::vector, but it is less+  // efficient because it requires an extra memory allocation.+  Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(+      info.Env(),+      nativeArray->data(),+      arrayLength /* size in bytes */,+      [](Napi::Env /*env*/, void* /*data*/, std::vector<uint8_t>* hint) {+        std::unique_ptr<std::vector<uint8_t>> vectorPtrToDelete(hint);+      },+      nativeArray.get());+  // The finalizer is responsible for deleting the vector: release the+  // unique_ptr ownership.+  nativeArray.release();++  Napi::Uint8Array byteArray =+      Napi::Uint8Array::New(info.Env(), arrayLength, arrayBuffer, 0);++  return byteArray;+}++static Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports["AcceptByteArray"] = Napi::Function::New(env, AcceptByteArray);+  exports["CreateByteArray"] = Napi::Function::New(env, CreateByteArray);+  return exports;+}++NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

src/3-context-awareness/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  'targets': [+    {+      'target_name': 'multiple_load',+      'sources': [ 'multiple_load.c' ]+    }+  ]+}

src/3-context-awareness/napi/index.js

new file mode 100644@@ -0,0 +1,40 @@+// Example illustrating the case where a native addon is loaded multiple times.+// This entire file is executed twice, concurrently - once on the main thread,+// and once on a thread launched from the main thread.++// We load the worker threads module, which allows us to launch multiple Node.js+// environments, each in its own thread.+const {+  Worker, isMainThread+} = require('worker_threads');++// We load the native addon.+const addon = require('bindings')('multiple_load');++// The iteration count can be tweaked to ensure that the output from the two+// threads is interleaved. Too few iterations and the output of one thread+// follows the output of the other, not really illustrating the concurrency.+const iterations = 1000;++// This function is an idle loop that performs a random walk from 0 by calling+// into the native addon to either increment or decrement the initial value.+function useAddon(addon, prefix, iterations) {+  if (iterations >= 0) {+    if (Math.random() < 0.5) {+      console.log(prefix + ': new value (decremented): ' + addon.decrement());+    } else {+      console.log(prefix + ': new value (incremented): ' + addon.increment());+    }+    setImmediate(() => useAddon(addon, prefix, --iterations));+  }+}++if (isMainThread) {+  // On the main thread, we launch a worker and wait for it to come online. Then+  // we start the loop.+  (new Worker(__filename)).on('online',+      () => useAddon(addon, "Main thread", iterations));+} else {+  // On the secondary thread we immediately start the loop.+  useAddon(addon, "Worker thread", iterations);+}

src/3-context-awareness/napi/multiple_load.c

new file mode 100644@@ -0,0 +1,145 @@+#include <stdio.h>+#include <math.h>+#include <stdlib.h>+#include <node_api.h>++#define CHECK(expr) \+  { \+    if ((expr) == 0) { \+      fprintf(stderr, "%s:%d: failed assertion `%s'\n", __FILE__, __LINE__, #expr); \+      fflush(stderr); \+      abort(); \+    } \+  }++// Structure containing information needed for as long as the addon exists. It+// replaces the use of global static data with per-addon-instance data by+// associating an instance of this structure with each instance of this addon+// during addon initialization. The instance of this structure is then passed to+// each binding the addon provides. Thus, the data stored in an instance of this+// structure is available to each binding, just as global static data would be.+typedef struct {+  double value;+} AddonData;++// This is the actual, useful work performed: increment or decrement the value+// stored per addon instance after passing it through a CPU-consuming but+// otherwise useless calculation.+static int ModifyAddonData(AddonData* data, double offset) {+    // Expensively increment or decrement the value.+    data->value = tan(atan(exp(log(sqrt(data->value * data->value))))) + offset;++    // Round the value to the nearest integer.+    data->value =+        (double)(((int)data->value) ++        (data->value - ((double)(int)data->value) > 0.5 ? 1 : 0));++    // Return the value as an integer.+    return (int)(data->value);+}++// This is boilerplate. The instance of the `AddonData` structure created during+// addon initialization must be destroyed when the addon is unloaded. This+// function will be called when the addon's `exports` object is garbage collected.+static void DeleteAddonData(napi_env env, void* data, void* hint) {+  // Avoid unused parameter warnings.+  (void) env;+  (void) hint;++  // Free the per-addon-instance data.+  free(data);+}++// This is also boilerplate. It creates and initializes an instance of the+// `AddonData` structure and ties its lifecycle to that of the addon instance's+// `exports` object. This means that the data will be available to this instance+// of the addon for as long as the JavaScript engine keeps it alive.+static AddonData* CreateAddonData(napi_env env, napi_value exports) {+  AddonData* result = malloc(sizeof(*result));+  result->value = 0.0;+  CHECK(napi_wrap(env,+                   exports,+                   result,+                   DeleteAddonData,+                   NULL,+                   NULL) == napi_ok);+  return result;+}++// This function is called from JavaScript. It uses an expensive operation to+// increment the value stored inside the `AddonData` structure by one.+static napi_value Increment(napi_env env, napi_callback_info info) {+  // Retrieve the per-addon-instance data.+  AddonData* addon_data = NULL;+  CHECK(napi_get_cb_info(env,+                          info,+                          NULL,+                          NULL,+                          NULL,+                          ((void**)&addon_data)) == napi_ok);++  // Increment the per-addon-instance value and create a new JavaScript integer+  // from it.+  napi_value result;+  CHECK(napi_create_int32(env,+                           ModifyAddonData(addon_data, 1.0),+                           &result) == napi_ok);++  // Return the JavaScript integer back to JavaScript.+  return result;+}++// This function is called from JavaScript. It uses an expensive operation to+// decrement the value stored inside the `AddonData` structure by one.+static napi_value Decrement(napi_env env, napi_callback_info info) {+  // Retrieve the per-addon-instance data.+  AddonData* addon_data = NULL;+  CHECK(napi_get_cb_info(env,+                          info,+                          NULL,+                          NULL,+                          NULL,+                          ((void**)&addon_data)) == napi_ok);++  // Decrement the per-addon-instance value and create a new JavaScript integer+  // from it.+  napi_value result;+  CHECK(napi_create_int32(env,+                           ModifyAddonData(addon_data, -1.0),+                           &result) == napi_ok);++  // Return the JavaScript integer back to JavaScript.+  return result;+}++// Initialize the addon in such a way that it may be initialized multiple times+// per process. The function body following this macro is provided the value+// `env` which has type `napi_env` and the value `exports` which has type+// `napi_value` and which refers to a JavaScript object that ultimately contains+// the functions this addon wishes to expose. At the end, it must return a+// `napi_value`. It may return `exports`, or it may create a new `napi_value`+// and return that instead.+NAPI_MODULE_INIT(/*env, exports*/) {+  // Create a new instance of the per-instance-data that will be associated with+  // the instance of the addon being initialized here and that will be destroyed+  // along with the instance of the addon.+  AddonData* addon_data = CreateAddonData(env, exports);++  // Declare the bindings this addon provides. The data created above is given+  // as the last initializer parameter, and will be given to the binding when it+  // is called.+  napi_property_descriptor bindings[] = {+    {"increment", NULL, Increment, NULL, NULL, NULL, napi_enumerable, addon_data},+    {"decrement", NULL, Decrement, NULL, NULL, NULL, napi_enumerable, addon_data}+  };++  // Expose the two bindings declared above to JavaScript.+  CHECK(napi_define_properties(env,+                                exports,+                                sizeof(bindings) / sizeof(bindings[0]),+                                bindings) == napi_ok);++  // Return the `exports` object provided. It now has two new properties, which+  // are the functions we wish to expose to JavaScript.+  return exports;+}

src/3-context-awareness/napi/package.json

new file mode 100644@@ -0,0 +1,17 @@+{+  "name": "multiple_load",+  "version": "0.0.0",+  "description": "Multiple load example",+  "main": "index.js",+  "private": true,+  "scripts": {+    "test": "node --experimental-worker index.js"+  },+  "engines": {+    "node": ">= 10.10.0"+  },+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.2.1"+  }+}

src/3-context-awareness/node_10/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  'targets': [+    {+      'target_name': 'multiple_load',+      'sources': [ 'multiple_load.cc' ]+    }+  ]+}

src/3-context-awareness/node_10/index.js

new file mode 100644@@ -0,0 +1,40 @@+// Example illustrating the case where a native addon is loaded multiple times.+// This entire file is executed twice, concurrently - once on the main thread,+// and once on a thread launched from the main thread.++// We load the worker threads module, which allows us to launch multiple Node.js+// environments, each in its own thread.+const {+  Worker, isMainThread+} = require('worker_threads');++// We load the native addon.+const addon = require('bindings')('multiple_load');++// The iteration count can be tweaked to ensure that the output from the two+// threads is interleaved. Too few iterations and the output of one thread+// follows the output of the other, not really illustrating the concurrency.+const iterations = 1000;++// This function is an idle loop that performs a random walk from 0 by calling+// into the native addon to either increment or decrement the initial value.+function useAddon(addon, prefix, iterations) {+  if (iterations >= 0) {+    if (Math.random() < 0.5) {+      console.log(prefix + ': new value (decremented): ' + addon.decrement());+    } else {+      console.log(prefix + ': new value (incremented): ' + addon.increment());+    }+    setImmediate(() => useAddon(addon, prefix, --iterations));+  }+}++if (isMainThread) {+  // On the main thread, we launch a worker and wait for it to come online. Then+  // we start the loop.+  (new Worker(__filename)).on('online',+      () => useAddon(addon, "Main thread", iterations));+} else {+  // On the secondary thread we immediately start the loop.+  useAddon(addon, "Worker thread", iterations);+}

src/3-context-awareness/node_10/multiple_load.cc

new file mode 100644@@ -0,0 +1,121 @@+#include <math.h>+#include <node.h>++using namespace v8;++// Class containing information needed for as long as the addon exists. It+// replaces the use of global static data with per-addon-instance data by+// associating an instance of this class with each instance of this addon during+// addon initialization. The instance of this class is then passed to each+// binding the addon provides. Thus, the data stored in an instance of this+// class is available to each binding, just as global static data would be.+class AddonData {+ public:+  // This is the actual, useful work performed: increment or decrement the value+  // stored per addon instance after passing it through a CPU-consuming but+  // otherwise useless calculation. Round the result to the nearest integer.+  int GetNewValue(double offset) {+    // Expensively increment or decrement the value.+    value = tan(atan(exp(log(sqrt(value * value))))) + offset;++    // Round the value to the nearest integer.+    value =+        (double)(((int)value) + (value - ((double)(int)value) > 0.5 ? 1 : 0));++    // Return the value as an integer.+    return (int)value;+  }++  // This is boilerplate. It creates a new instance of this class and wraps it+  // into a v8::External. The isolate and the exports are necessary, because we+  // want the instance of this class to be destroyed along with the exports+  // object when the addon is eventually unloaded.+  static Local<Value> New(Isolate* isolate, Local<Object> exports) {+    return External::New(isolate, new AddonData(isolate, exports));+  }++ private:+  // This is the actual, useful payload carried by an instance of this class.+  // A double value is kept around for as long as an instance of this addon is+  // loaded, and is incremented or decremented whenever the addon receives a+  // call from JavaScript.+  double value;++  explicit AddonData(Isolate* isolate, Local<Object> exports)+      :  // The payload is initialized here. The rest of the constructor is+         // boilerplate that ensures that the instance of this addon data is+         // destroyed along with the instance of this addon (`exports`).+        value(0.0) {+    exports_persistent.Reset(isolate, exports);+    exports_persistent.SetWeak(this, DeleteMe, WeakCallbackType::kParameter);+  }++  // The rest of the class definition is boilerplate.++  // The persistent reference must be reset before the instance of this class is+  // destroyed, otherwise memory will leak on the V8 side.+  ~AddonData() { exports_persistent.Reset(); }++  // This static function will be called when the addon instance is unloaded. It+  // merely destroys the per-addon-instance data.+  static void DeleteMe(const WeakCallbackInfo<AddonData>& info) {+    delete info.GetParameter();+  }++  Persistent<Object> exports_persistent;+};++// Function called from JavaScript to increment the value stored in this addon.+void Increment(const FunctionCallbackInfo<Value>& info) {+  // Retrieve the per-addon-instance data.+  AddonData* addon_data =+      static_cast<AddonData*>(info.Data().As<External>()->Value());++  info.GetReturnValue().Set(+      Number::New(info.GetIsolate(), addon_data->GetNewValue(1.0)));+}++// Function called from JavaScript to decrement the value stored in this addon.+void Decrement(const FunctionCallbackInfo<Value>& info) {+  // Retrieve the per-addon-instance data.+  AddonData* addon_data =+      static_cast<AddonData*>(info.Data().As<External>()->Value());++  info.GetReturnValue().Set(+      Number::New(info.GetIsolate(), addon_data->GetNewValue(-1.0)));+}++// Initialize the addon in such a way that it may be initialized multiple times+// per process. The function body following this macro is provided the value+// `exports` of type `Local<Object>`, the value `module` of type+// `Local<Object>`, and `context` of type `Local<Context>`. It may either define+// new properties on the `exports` object, or define the property named+// "exports" on the `module` object.+NODE_MODULE_INIT(/*exports, module, context*/) {+  Isolate* isolate = context->GetIsolate();++  // Create a new instance of the addon data that will be associated with this+  // instance of the addon, and that will be freed along with this instance of+  // the addon.+  Local<Value> addon_data = AddonData::New(isolate, exports);++  // Export the functions we wish to make available to JavaScript.++  exports+      ->Set(context,+            String::NewFromUtf8(isolate, "increment", NewStringType::kNormal)+                .ToLocalChecked(),+            FunctionTemplate::New(isolate, Increment, addon_data)+                ->GetFunction(context)+                .ToLocalChecked())+      .FromJust();++  exports+      ->Set(context,+            String::NewFromUtf8(isolate, "decrement", NewStringType::kNormal)+                .ToLocalChecked(),+            FunctionTemplate::New(isolate, Decrement, addon_data)+                ->GetFunction(context)+                .ToLocalChecked())+      .FromJust();+}

src/3-context-awareness/node_10/package.json

new file mode 100644@@ -0,0 +1,17 @@+{+  "name": "multiple_load",+  "version": "0.0.0",+  "description": "Multiple load example",+  "main": "index.js",+  "private": true,+  "scripts": {+    "test": "node --experimental-worker index.js"+  },+  "engines": {+    "node": ">= 10.10.0"+  },+  "gypfile": true,+  "dependencies": {+    "bindings": "~1.2.1"+  }+}

src/4-references-and-handle-scope/function-reference-demo/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,31 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [+        "src/binding.cc",+        "src/native-addon.cc"+      ],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'conditions': [+        ['OS=="win"', {+          "msvs_settings": {+            "VCCLCompilerTool": {+              "ExceptionHandling": 1+            }+          }+        }],+        ['OS=="mac"', {+          "xcode_settings": {+            "CLANG_CXX_LIBRARY": "libc++",+            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+            'MACOSX_DEPLOYMENT_TARGET': '10.7'+          }+        }]+      ]+    }+  ]+}

src/4-references-and-handle-scope/function-reference-demo/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,27 @@+'use strict'++const { NativeAddon } = require('bindings')('addon')++function JSFnRef() {+    console.log('Hi! I\'m a JS function reference!')+}++function JSFn() {+    console.log('Hi! I\'m a JS function!')+}++const ITERATIONS = 5++const addon = new NativeAddon(JSFnRef, JSFn)++for (let i = 0; i < ITERATIONS; i++) {+    addon.tryCallByStoredReference()+}++try {+    addon.tryCallByStoredFunction()+} catch (err) {+    console.error('This code crashes because JSFn is valid only inside the constructor function.')+    console.error('The lifespan of the JSFn function is limited to the execution of the constructor function.')+    console.error('After that, the function stored in JSFn is ready to be garbage collected and it cannot be used anymore.')+}

src/4-references-and-handle-scope/function-reference-demo/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,14 @@+{+  "name": "function-reference-demo",+  "version": "0.0.0",+  "description": "Tutorial example showing the use of function references.",+  "main": "index.js",+  "gypfile": true,+  "scripts": {+    "start": "node index.js"+  },+  "dependencies": {+    "node-addon-api": "*",+    "bindings": "*"+  }+}

src/4-references-and-handle-scope/function-reference-demo/node-addon-api/src/binding.cc

new file mode 100644@@ -0,0 +1,9 @@+#include <napi.h>+#include "native-addon.h"++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  NativeAddon::Init(env, exports);+  return exports;+}++NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)\ No newline at end of file

src/4-references-and-handle-scope/function-reference-demo/node-addon-api/src/native-addon.cc

new file mode 100644@@ -0,0 +1,36 @@+#include "native-addon.h"+#include <iostream>++Napi::FunctionReference NativeAddon::constructor;++Napi::Object NativeAddon::Init(Napi::Env env, Napi::Object exports) {+  Napi::Function func =+      DefineClass(env,+                  "NativeAddon",+                  {InstanceMethod("tryCallByStoredReference",+                                  &NativeAddon::TryCallByStoredReference),+                   InstanceMethod("tryCallByStoredFunction",+                                  &NativeAddon::TryCallByStoredFunction)});++  constructor = Napi::Persistent(func);+  constructor.SuppressDestruct();++  exports.Set("NativeAddon", func);+  return exports;+}++NativeAddon::NativeAddon(const Napi::CallbackInfo& info)+    : Napi::ObjectWrap<NativeAddon>(info) {+  jsFnRef = Napi::Persistent(info[0].As<Napi::Function>());+  jsFn = info[1].As<Napi::Function>();+}++void NativeAddon::TryCallByStoredReference(const Napi::CallbackInfo& info) {+  // Napi::Env env = info.Env();+  jsFnRef.Call({});+}++void NativeAddon::TryCallByStoredFunction(const Napi::CallbackInfo& info) {+  // Napi::Env env = info.Env();+  jsFn.Call({});+}\ No newline at end of file

src/4-references-and-handle-scope/function-reference-demo/node-addon-api/src/native-addon.h

new file mode 100644@@ -0,0 +1,15 @@+#include <napi.h>++class NativeAddon : public Napi::ObjectWrap<NativeAddon> {+ public:+  static Napi::Object Init(Napi::Env env, Napi::Object exports);+  NativeAddon(const Napi::CallbackInfo& info);++ private:+  static Napi::FunctionReference constructor;+  Napi::FunctionReference jsFnRef;+  Napi::Function jsFn;++  void TryCallByStoredReference(const Napi::CallbackInfo& info);+  void TryCallByStoredFunction(const Napi::CallbackInfo& info);+};\ No newline at end of file

src/5-async-work/async-iterator/node-addon-api/CMakeLists.txt

new file mode 100644@@ -0,0 +1,23 @@+project (example)+include_directories(${CMAKE_JS_INC} node_modules/node-addon-api/)+cmake_minimum_required(VERSION 3.18)++set(CMAKE_CXX_STANDARD 20)+set(CMAKE_CXX_STANDARD_REQUIRED ON)+include_directories(${CMAKE_JS_INC})+file(GLOB SOURCE_FILES "*.cc")+add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")+target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})++# Include Node-API wrappers+execute_process(COMMAND node -p "require('node-addon-api').include"+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}+        OUTPUT_VARIABLE NODE_ADDON_API_DIR+        )+string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})++target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})++# define NAPI_VERSION+add_definitions(-DNAPI_VERSION=6)

src/5-async-work/async-iterator/node-addon-api/example.cc

new file mode 100644@@ -0,0 +1,84 @@+#include <napi.h>+#include <memory>++using namespace Napi;++class AsyncIteratorExample : public ObjectWrap<AsyncIteratorExample> {+ public:+  AsyncIteratorExample(const CallbackInfo& info)+      : ObjectWrap<AsyncIteratorExample>(info),+        _from(info[0].As<Number>()),+        _to(info[1].As<Number>()) {}++  static Object Init(Napi::Env env, Napi::Object exports) {+    Napi::Function func = DefineClass(+        env,+        "AsyncIteratorExample",+        {InstanceMethod(Napi::Symbol::WellKnown(env, "asyncIterator"),+                        &AsyncIteratorExample::Iterator)});++    exports.Set("AsyncIteratorExample", func);+    return exports;+  }++  Napi::Value Iterator(const CallbackInfo& info) {+    auto env = info.Env();+    auto iteratorObject = Napi::Object::New(env);++    iteratorObject["current"] = Number::New(env, _from);+    iteratorObject["last"] = Number::New(env, _to);+    auto next = Function::New(env, [](const CallbackInfo& info) {+      auto env = info.Env();+      auto deferred =+          std::make_shared<Promise::Deferred>(Promise::Deferred::New(env));+      auto iteratorObject = info.This().As<Object>();+      auto callback = Function::New(+          env,+          [=](const CallbackInfo& info) {+            auto env = info.Env();+            auto value = Object::New(env);+            auto iteratorObject = info.This().As<Object>();++            auto current =+                iteratorObject.Get("current").As<Number>().Int32Value();+            auto last = iteratorObject.Get("last").As<Number>().Int32Value();+            auto done = current > last;++            if (done) {+              value["done"] = Boolean::New(env, true);+            } else {+              value["done"] = Boolean::New(env, false);+              value["value"] = Number::New(env, current);+              iteratorObject["current"] = Number::New(env, current + 1);+            }+            deferred->Resolve(value);+          },+          "next");++      env.Global()+          .Get("setTimeout")+          .As<Function>()+          .Call({callback.Get("bind").As<Function>().Call(callback,+                                                          {iteratorObject}),+                 Number::New(env, 1000)});++      return deferred->Promise();+    });++    iteratorObject["next"] =+        next.Get("bind").As<Function>().Call(next, {iteratorObject});++    return iteratorObject;+  }++ private:+  int _from;+  int _to;+};++Napi::Object Init(Napi::Env env, Object exports) {+  AsyncIteratorExample::Init(env, exports);+  return exports;+}++NODE_API_MODULE(example, Init)

src/5-async-work/async-iterator/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,49 @@+const { AsyncIteratorExample } = require('bindings')('example');++async function main(from, to) {+    const iterator = new AsyncIteratorExample(from, to);+    for await (const value of iterator) {+        console.log(value);+    }+}++/*+// The JavaScript equivalent of the node-addon-api C++ code for reference+async function main(from, to) {+    class AsyncIteratorExample {+        constructor(from, to) {+            this.from = from;+            this.to = to;+        }++        [Symbol.asyncIterator]() {+            return {+                current: this.from,+                last: this.to,+                next() {+                    return new Promise(resolve => {+                        setTimeout(() => {+                            if (this.current <= this.last) {+                                resolve({ done: false, value: this.current++ });+                            } else {+                                resolve({ done: true });+                            }+                        }, 1000)+                    });+                }+            }+        }+    }+    const iterator = new AsyncIteratorExample(from, to);++    for await (const value of iterator) {+        console.log(value);+    }+}+*/++main(0, 5)+    .catch(e => {+        console.error(e);+        process.exit(1);+    });

src/5-async-work/async-iterator/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,16 @@+{+  "name": "async-iterator-example",+  "version": "0.0.0",+  "description": "Async iterator example using node-addon-api",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "^1.5.0",+    "cmake-js": "^6.3.0",+    "node-addon-api": "^5.0.0"+  },+  "scripts": {+    "test": "node index.js",+    "install": "cmake-js compile"+  }+}

src/5-async-work/async_pi_estimate/nan/README.md

new file mode 100755@@ -0,0 +1 @@+In this directory run `node-gyp rebuild` and then `node ./addon.js`\ No newline at end of file

src/5-async-work/async_pi_estimate/nan/addon.cc

new file mode 100755@@ -0,0 +1,24 @@+#include <nan.h>+#include "async.h"  // NOLINT(build/include)+#include "sync.h"   // NOLINT(build/include)++using Nan::GetFunction;+using Nan::New;+using Nan::Set;+using v8::FunctionTemplate;+using v8::Object;+using v8::String;++// Expose synchronous and asynchronous access to our+// Estimate() function+NAN_MODULE_INIT(InitAll) {+  Set(target,+      New<String>("calculateSync").ToLocalChecked(),+      GetFunction(New<FunctionTemplate>(CalculateSync)).ToLocalChecked());++  Set(target,+      New<String>("calculateAsync").ToLocalChecked(),+      GetFunction(New<FunctionTemplate>(CalculateAsync)).ToLocalChecked());+}++NODE_MODULE(addon, InitAll)

src/5-async-work/async_pi_estimate/nan/addon.js

new file mode 100755@@ -0,0 +1,44 @@+var addon = require('./build/Release/addon');+var calculations = process.argv[2] || 100000000;++function printResult(type, pi, ms) {+  console.log(type, 'method:');+  console.log('\tπ ≈ ' + pi ++              ' (' + Math.abs(pi - Math.PI) + ' away from actual)');+  console.log('\tTook ' + ms + 'ms');+  console.log();+}++function runSync() {+  var start = Date.now();+  // Estimate() will execute in the current thread,+  // the next line won't return until it is finished+  var result = addon.calculateSync(calculations);+  printResult('Sync', result, Date.now() - start);+}++function runAsync() {+  // how many batches should we split the work in to?+  var batches = process.argv[3] || 16;+  var ended = 0;+  var total = 0;+  var start = Date.now();++  function done (err, result) {+    total += result;++    // have all the batches finished executing?+    if (++ended === batches) {+      printResult('Async', total / batches, Date.now() - start);+    }+  }++  // for each batch of work, request an async Estimate() for+  // a portion of the total number of calculations+  for (var i = 0; i < batches; i++) {+    addon.calculateAsync(calculations / batches, done);+  }+}++runSync();+runAsync();

src/5-async-work/async_pi_estimate/nan/async.cc

new file mode 100755@@ -0,0 +1,51 @@+#include "async.h"  // NOLINT(build/include)+#include <nan.h>+#include "pi_est.h"  // NOLINT(build/include)++using Nan::AsyncQueueWorker;+using Nan::AsyncWorker;+using Nan::Callback;+using Nan::HandleScope;+using Nan::New;+using Nan::Null;+using Nan::To;+using v8::Function;+using v8::Local;+using v8::Number;+using v8::Value;++class PiWorker : public AsyncWorker {+ public:+  PiWorker(Callback* callback, int points)+      : AsyncWorker(callback), points(points), estimate(0) {}+  ~PiWorker() {}++  // Executed inside the worker-thread.+  // It is not safe to access V8, or V8 data structures+  // here, so everything we need for input and output+  // should go on `this`.+  void Execute() { estimate = Estimate(points); }++  // Executed when the async work is complete+  // this function will be run inside the main event loop+  // so it is safe to use V8 again+  void HandleOKCallback() {+    HandleScope scope;++    Local<Value> argv[] = {Null(), New<Number>(estimate)};++    callback->Call(2, argv, async_resource);+  }++ private:+  int points;+  double estimate;+};++// Asynchronous access to the `Estimate()` function+NAN_METHOD(CalculateAsync) {+  int points = To<int>(info[0]).FromJust();+  Callback* callback = new Callback(To<Function>(info[1]).ToLocalChecked());++  AsyncQueueWorker(new PiWorker(callback, points));+}

src/5-async-work/async_pi_estimate/nan/async.h

new file mode 100755@@ -0,0 +1,8 @@+#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_+#define EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_++#include <nan.h>++NAN_METHOD(CalculateAsync);++#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_

src/5-async-work/async_pi_estimate/nan/binding.gyp

new file mode 100755@@ -0,0 +1,14 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [+        "addon.cc",+        "pi_est.cc",+        "sync.cc",+        "async.cc"+      ],+      "include_dirs": ["<!(node -e \"require('nan')\")"]+    }+  ]+}

src/5-async-work/async_pi_estimate/nan/package.json

new file mode 100755@@ -0,0 +1,14 @@+{+  "name": "async_work",+  "version": "0.0.0",+  "description": "Node.js Addons Example #9",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "scripts": {+    "test": "node addon.js"+  },+  "dependencies": {+    "nan": "*"+  }+}

src/5-async-work/async_pi_estimate/nan/pi_est.cc

new file mode 100755@@ -0,0 +1,54 @@+#include "pi_est.h"  // NOLINT(build/include)+#include <cstdlib>++/*+Estimate the value of π by using a Monte Carlo method.+Take `points` samples of random x and y values on a+[0,1][0,1] plane. Calculating the length of the diagonal+tells us whether the point lies inside, or outside a+quarter circle running from 0,1 to 1,0. The ratio of the+number of points inside to outside gives us an+approximation of π/4.++See https://en.wikipedia.org/wiki/File:Pi_30K.gif+for a visualization of how this works.+*/++inline int randall(unsigned int* p_seed) {+// windows has thread safe rand()+#ifdef _WIN32+  return rand();  // NOLINT(runtime/threadsafe_fn)+#else+  return rand_r(p_seed);+#endif+}++double Estimate(int points) {+  int i = points;+  int inside = 0;+  unsigned int randseed = 1;++#ifdef _WIN32+  srand(randseed);+#endif++  // unique seed for each run, for threaded use+  unsigned int seed = randall(&randseed);++#ifdef _WIN32+  srand(seed);+#endif++  while (i-- > 0) {+    double x = randall(&seed) / static_cast<double>(RAND_MAX);+    double y = randall(&seed) / static_cast<double>(RAND_MAX);++    // x & y and now values between 0 and 1+    // now do a pythagorean diagonal calculation+    // `1` represents our 1/4 circle+    if ((x * x) + (y * y) <= 1) inside++;+  }++  // calculate ratio and multiply by 4 for π+  return (inside / static_cast<double>(points)) * 4;+}

src/5-async-work/async_pi_estimate/nan/pi_est.h

new file mode 100755@@ -0,0 +1,6 @@+#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_+#define EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_++double Estimate(int points);++#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_

src/5-async-work/async_pi_estimate/nan/sync.cc

new file mode 100755@@ -0,0 +1,12 @@+#include "sync.h"  // NOLINT(build/include)+#include <nan.h>+#include "pi_est.h"  // NOLINT(build/include)++// Simple synchronous access to the `Estimate()` function+NAN_METHOD(CalculateSync) {+  // expect a number as the first argument+  int points = info[0]->Uint32Value(Nan::GetCurrentContext()).FromJust();+  double est = Estimate(points);++  info.GetReturnValue().Set(est);+}

src/5-async-work/async_pi_estimate/nan/sync.h

new file mode 100755@@ -0,0 +1,8 @@+#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_+#define EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_++#include <nan.h>++NAN_METHOD(CalculateSync);++#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_

src/5-async-work/async_pi_estimate/node-addon-api/README.md

new file mode 100755@@ -0,0 +1 @@+In this directory run `node-gyp rebuild` and then `node ./addon.js`\ No newline at end of file

src/5-async-work/async_pi_estimate/node-addon-api/addon.cc

new file mode 100755@@ -0,0 +1,15 @@+#include <napi.h>+#include "async.h"  // NOLINT(build/include)+#include "sync.h"   // NOLINT(build/include)++// Expose synchronous and asynchronous access to our+// Estimate() function+Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "calculateSync"),+              Napi::Function::New(env, CalculateSync));+  exports.Set(Napi::String::New(env, "calculateAsync"),+              Napi::Function::New(env, CalculateAsync));+  return exports;+}++NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

src/5-async-work/async_pi_estimate/node-addon-api/addon.js

new file mode 100755@@ -0,0 +1,44 @@+var addon = require('bindings')('addon');+var calculations = process.argv[2] || 100000000;++function printResult(type, pi, ms) {+  console.log(type, 'method:');+  console.log('\tπ ≈ ' + pi ++              ' (' + Math.abs(pi - Math.PI) + ' away from actual)');+  console.log('\tTook ' + ms + 'ms');+  console.log();+}++function runSync() {+  var start = Date.now();+  // Estimate() will execute in the current thread,+  // the next line won't return until it is finished+  var result = addon.calculateSync(calculations);+  printResult('Sync', result, Date.now() - start);+}++function runAsync() {+  // how many batches should we split the work in to?+  var batches = process.argv[3] || 16;+  var ended = 0;+  var total = 0;+  var start = Date.now();++  function done (err, result) {+    total += result;++    // have all the batches finished executing?+    if (++ended === batches) {+      printResult('Async', total / batches, Date.now() - start);+    }+  }++  // for each batch of work, request an async Estimate() for+  // a portion of the total number of calculations+  for (var i = 0; i < batches; i++) {+    addon.calculateAsync(calculations / batches, done);+  }+}++runSync();+runAsync();

src/5-async-work/async_pi_estimate/node-addon-api/async.cc

new file mode 100755@@ -0,0 +1,36 @@+#include "async.h"  // NOLINT(build/include)+#include <napi.h>+#include "pi_est.h"  // NOLINT(build/include)++class PiWorker : public Napi::AsyncWorker {+ public:+  PiWorker(Napi::Function& callback, int points)+      : Napi::AsyncWorker(callback), points(points), estimate(0) {}+  ~PiWorker() {}++  // Executed inside the worker-thread.+  // It is not safe to access JS engine data structure+  // here, so everything we need for input and output+  // should go on `this`.+  void Execute() { estimate = Estimate(points); }++  // Executed when the async work is complete+  // this function will be run inside the main event loop+  // so it is safe to use JS engine data again+  void OnOK() {+    Callback().Call({Env().Undefined(), Napi::Number::New(Env(), estimate)});+  }++ private:+  int points;+  double estimate;+};++// Asynchronous access to the `Estimate()` function+Napi::Value CalculateAsync(const Napi::CallbackInfo& info) {+  int points = info[0].As<Napi::Number>().Uint32Value();+  Napi::Function callback = info[1].As<Napi::Function>();+  PiWorker* piWorker = new PiWorker(callback, points);+  piWorker->Queue();+  return info.Env().Undefined();+}

src/5-async-work/async_pi_estimate/node-addon-api/async.h

new file mode 100755@@ -0,0 +1,8 @@+#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_+#define EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_++#include <napi.h>++Napi::Value CalculateAsync(const Napi::CallbackInfo& info);++#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_ASYNC_H_

src/5-async-work/async_pi_estimate/node-addon-api/binding.gyp

new file mode 100755@@ -0,0 +1,33 @@+{+  "targets": [+    {+      "target_name": "addon",+      "sources": [+        "addon.cc",+        "pi_est.cc",+        "sync.cc",+        "async.cc"+      ],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'conditions': [+        ['OS=="win"', {+          "msvs_settings": {+            "VCCLCompilerTool": {+              "ExceptionHandling": 1+            }+          }+        }],+        ['OS=="mac"', {+          "xcode_settings": {+            "CLANG_CXX_LIBRARY": "libc++",+            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+            'MACOSX_DEPLOYMENT_TARGET': '10.7'+          }+        }]+      ]+    }+  ]+}

src/5-async-work/async_pi_estimate/node-addon-api/package.json

new file mode 100755@@ -0,0 +1,15 @@+{+  "name": "async_work",+  "version": "0.0.0",+  "description": "Node.js Addons Example #9",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "scripts": {+    "test": "node addon.js"+  },+  "dependencies": {+    "node-addon-api": "*",+    "bindings": "*"+  }+}

src/5-async-work/async_pi_estimate/node-addon-api/pi_est.cc

new file mode 100755@@ -0,0 +1,54 @@+#include "pi_est.h"  // NOLINT(build/include)+#include <cstdlib>++/*+Estimate the value of π by using a Monte Carlo method.+Take `points` samples of random x and y values on a+[0,1][0,1] plane. Calculating the length of the diagonal+tells us whether the point lies inside, or outside a+quarter circle running from 0,1 to 1,0. The ratio of the+number of points inside to outside gives us an+approximation of π/4.++See https://en.wikipedia.org/wiki/File:Pi_30K.gif+for a visualization of how this works.+*/++inline int randall(unsigned int* p_seed) {+// windows has thread safe rand()+#ifdef _WIN32+  return rand();  // NOLINT(runtime/threadsafe_fn)+#else+  return rand_r(p_seed);+#endif+}++double Estimate(int points) {+  int i = points;+  int inside = 0;+  unsigned int randseed = 1;++#ifdef _WIN32+  srand(randseed);+#endif++  // unique seed for each run, for threaded use+  unsigned int seed = randall(&randseed);++#ifdef _WIN32+  srand(seed);+#endif++  while (i-- > 0) {+    double x = randall(&seed) / static_cast<double>(RAND_MAX);+    double y = randall(&seed) / static_cast<double>(RAND_MAX);++    // x & y and now values between 0 and 1+    // now do a pythagorean diagonal calculation+    // `1` represents our 1/4 circle+    if ((x * x) + (y * y) <= 1) inside++;+  }++  // calculate ratio and multiply by 4 for π+  return (inside / static_cast<double>(points)) * 4;+}

src/5-async-work/async_pi_estimate/node-addon-api/pi_est.h

new file mode 100755@@ -0,0 +1,6 @@+#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_+#define EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_++double Estimate(int points);++#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_PI_EST_H_

src/5-async-work/async_pi_estimate/node-addon-api/sync.cc

new file mode 100755@@ -0,0 +1,12 @@+#include "sync.h"  // NOLINT(build/include)+#include <napi.h>+#include "pi_est.h"  // NOLINT(build/include)++// Simple synchronous access to the `Estimate()` function+Napi::Value CalculateSync(const Napi::CallbackInfo& info) {+  // expect a number as the first argument+  int points = info[0].As<Napi::Number>().Uint32Value();+  double est = Estimate(points);++  return Napi::Number::New(info.Env(), est);+}

src/5-async-work/async_pi_estimate/node-addon-api/sync.h

new file mode 100755@@ -0,0 +1,8 @@+#ifndef EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_+#define EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_++#include <napi.h>++Napi::Value CalculateSync(const Napi::CallbackInfo& info);++#endif  // EXAMPLES_ASYNC_PI_ESTIMATE_SYNC_H_

src/5-async-work/async_work_promise/napi/binding.c

new file mode 100644@@ -0,0 +1,170 @@+#include <stdio.h>+#include <stdlib.h>+#include <node_api.h>++// Limit ourselves to this many primes, starting at 2+#define PRIME_COUNT 10+#define CHECK(expr) \+  { \+    if ((expr) == 0) { \+      fprintf(stderr, "%s:%d: failed assertion `%s'\n", __FILE__, __LINE__, #expr); \+      fflush(stderr); \+      abort(); \+    } \+  }++typedef struct linked_box_s linked_box_t;+struct linked_box_s {+  linked_box_t* prev;+  int the_prime;+};++typedef struct {+  napi_async_work work;+  napi_deferred deferred;+  int data[PRIME_COUNT];+} AddonData;++// This function runs on a worker thread. It has no access to the JavaScript.+static void ExecuteWork(napi_env env, void* data) {+  AddonData* addon_data = (AddonData*)data;+  int idx_inner, idx_outer;+  int prime_count = 0;++  // Find the first 1000 prime numbers using an extremely inefficient algorithm.+  for (idx_outer = 2; prime_count < PRIME_COUNT; idx_outer++) {+    for (idx_inner = 2; idx_inner < idx_outer; idx_inner++) {+      if (idx_outer % idx_inner == 0) {+        break;+      }+    }+    if (idx_inner < idx_outer) {+      continue;+    }++    // Save the prime number to the heap. The JavaScript marshaller (CallJs)+    // will free this item after having sent it to JavaScript.+    addon_data->data[prime_count] = idx_outer;+    ++prime_count;+  }+}++// This function runs on the main thread after `ExecuteWork` exits.+static void WorkComplete(napi_env env, napi_status status, void* data) {+  if (status != napi_ok) {+    return;+  }++  AddonData* addon_data = (AddonData*)data;+  napi_value array;+  CHECK(napi_create_array(env, &array) == napi_ok);++  for (uint32_t idx = 0; idx < PRIME_COUNT; idx++) {+    napi_value js_the_prime;++    // Convert the integer to a napi_value.+    CHECK(napi_create_int32(env, addon_data->data[idx], &js_the_prime) == napi_ok);++    // Store the js value in the array.+    CHECK(napi_set_element(env, array, idx, js_the_prime) == napi_ok);+  }+  CHECK(napi_resolve_deferred(env, addon_data->deferred, array) == napi_ok);++  // Clean up the work item associated with this run.+  CHECK(napi_delete_async_work(env, addon_data->work) == napi_ok);++  // Set both values to NULL so JavaScript can order a new run of the thread.+  addon_data->work = NULL;+  addon_data->deferred = NULL;+}++// Create a deferred promise and an async queue work item.+static napi_value StartWork(napi_env env, napi_callback_info info) {+  napi_value work_name, promise;+  AddonData* addon_data;++  // Retrieve the per-addon data.+  CHECK(napi_get_cb_info(env,+                          info,+                          NULL,+                          NULL,+                          NULL,+                          (void**)(&addon_data)) == napi_ok);++  // Ensure that no work is currently in progress.+  CHECK(addon_data->work == NULL && "Only one work item must exist at a time");++  // Create a string to describe this asynchronous operation.+  CHECK(napi_create_string_utf8(env,+                                 "Node-API Deferred Promise from Async Work Item",+                                 NAPI_AUTO_LENGTH,+                                 &work_name) == napi_ok);++  // Create a deferred promise which we will resolve at the completion of the work.+  CHECK(napi_create_promise(env,+                             &(addon_data->deferred),+                             &promise) == napi_ok);++  // Create an async work item, passing in the addon data, which will give the+  // worker thread access to the above-created deferred promise.+  CHECK(napi_create_async_work(env,+                                NULL,+                                work_name,+                                ExecuteWork,+                                WorkComplete,+                                addon_data,+                                &(addon_data->work)) == napi_ok);++  // Queue the work item for execution.+  CHECK(napi_queue_async_work(env, addon_data->work) == napi_ok);++  // This causes created `promise` to be returned to JavaScript.+  return promise;+}++// Free the per-addon-instance data.+static void addon_getting_unloaded(napi_env env, void* data, void* hint) {+  AddonData* addon_data = (AddonData*)data;+  CHECK(addon_data->work == NULL &&+      "No work item in progress at module unload");+  free(addon_data);+}++// The commented-out return type and the commented out formal function+// parameters below help us keep in mind the signature of the addon+// initialization function. We write the body as though the return value were as+// commented below and as though there were parameters passed in as commented+// below.+/*napi_value*/ NAPI_MODULE_INIT(/*napi_env env, napi_value exports*/) {++  // Define addon-level data associated with this instance of the addon.+  AddonData* addon_data = (AddonData*)malloc(sizeof(*addon_data));+  addon_data->work = NULL;++  // Define the properties that will be set on exports.+  napi_property_descriptor start_work = {+    "startWork",+    NULL,+    StartWork,+    NULL,+    NULL,+    NULL,+    napi_default,+    addon_data+  };++  // Decorate exports with the above-defined properties.+  CHECK(napi_define_properties(env, exports, 1, &start_work) == napi_ok);++  // Associate the addon data with the exports object, to make sure that when+  // the addon gets unloaded our data gets freed.+  CHECK(napi_wrap(env,+                   exports,+                   addon_data,+                   addon_getting_unloaded,+                   NULL,+                   NULL) == napi_ok);++  // Return the decorated exports object.+  return exports;+}

src/5-async-work/async_work_promise/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  'targets': [+    {+      'target_name': 'binding',+      'sources': [ 'binding.c' ]+    }+  ]+}

src/5-async-work/async_work_promise/napi/index.js

new file mode 100644@@ -0,0 +1,10 @@+// Use the "bindings" package to locate the native bindings.+const binding = require('bindings')('binding');++// Call the function "startWork" which the native bindings library exposes.+// The function returns a promise which will be resolved at the complete of the+// work with an array of worked out primes. This resolution simply prints them out.+binding.startWork()+  .then((thePrimes) => {+    console.log("Received primes from completed work: " + thePrimes)+  });

src/5-async-work/async_work_promise/napi/package.json

new file mode 100644@@ -0,0 +1,17 @@+{+  "name": "async_work_promise",+  "version": "0.0.0",+  "description": "Calling into JS from the thread pool",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.5.0"+  },+  "engines": {+    "node": ">= 10.6.0"+  },+  "scripts": {+    "test": "node index.js"+  },+  "gypfile": true+}

src/5-async-work/async_work_promise/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,32 @@+#include "napi.h"+#include "worker.h"++Napi::Value DoHeavyMath(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();++  if (!info[0].IsNumber()) {+    Napi::TypeError::New(env, "num1 must be a number")+        .ThrowAsJavaScriptException();+    return env.Undefined();+  }+  uint32_t num_1 = info[0].As<Napi::Number>().Uint32Value();++  if (!info[1].IsNumber()) {+    Napi::TypeError::New(env, "num2 must be a number")+        .ThrowAsJavaScriptException();+    return env.Undefined();+  }+  uint32_t num_2 = info[1].As<Napi::Number>().Uint32Value();++  DoHeavyMathWorker* worker = new DoHeavyMathWorker(env, num_1, num_2);+  worker->Queue();+  return worker->GetPromise();+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "doHeavyMath"),+              Napi::Function::New(env, DoHeavyMath));+  return exports;+}++NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

src/5-async-work/async_work_promise/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,32 @@+{+  "targets": [{+    "target_name": "addon",+    "sources": [+      "addon.cc"+    ],+    "include_dirs": [+      "<!@(node -p \"require('node-addon-api').include\")"+    ],+    'defines': [ 'NAPI_CPP_EXCEPTIONS' ],+    'conditions': [+      [ 'OS=="win"', {+        'defines': [ '_HAS_EXCEPTIONS=1' ],+        'msvs_settings': {+          'VCCLCompilerTool': {+            'ExceptionHandling': 1,+          },+        },+      }],+      [ 'OS=="linux"', {+        "cflags": [ "-fexceptions" ],+        "cflags_cc": [ "-fexceptions" ],+      }],+      [ 'OS=="mac"', {+        'xcode_settings': {+          'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+          'CLANG_CXX_LIBRARY': 'libc++',+        }+      }]+    ],+  }]+}

src/5-async-work/async_work_promise/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,3 @@+const bindings = require("bindings")("addon");++bindings.doHeavyMath(2, 1).then(console.log);

src/5-async-work/async_work_promise/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "async_worker_promise",+  "version": "0.0.0",+  "description": "AsyncWorker example that returns a Promise",+  "main": "index.js",+  "scripts": {+    "test": "node ."+  },+  "author": "Matthew Keil (matthewkeil)",+  "gypfile": true,+  "dependencies": {+    "bindings": "^1.5.0",+    "node-addon-api": "^7.0.0"+  }+}

src/5-async-work/async_work_promise/node-addon-api/worker.h

new file mode 100644@@ -0,0 +1,43 @@+#include "napi.h"++class DoHeavyMathWorker : public Napi::AsyncWorker {+ public:+  DoHeavyMathWorker(const Napi::Env& env, uint32_t num_1, uint32_t num_2)+      : Napi::AsyncWorker{env, "DoHeavyMathWorker"},+        m_deferred{env},+        m_num_1{num_1},+        m_num_2{num_2} {}++  /**+   * GetPromise associated with _deferred for return to JS+   */+  Napi::Promise GetPromise() { return m_deferred.Promise(); }++ protected:+  /**+   * Simulate heavy math work+   */+  void Execute() {+    if (m_num_2 == 0) {+      SetError("Cannot divide by zero");+      return;+    }+    m_result = m_num_1 / m_num_2;+  }++  /**+   * Resolve the promise with the result+   */+  void OnOK() { m_deferred.Resolve(Napi::Number::New(Env(), m_result)); }++  /**+   * Reject the promise with errors+   */+  void OnError(const Napi::Error& err) { m_deferred.Reject(err.Value()); }++ private:+  Napi::Promise::Deferred m_deferred;+  uint32_t m_num_1;+  uint32_t m_num_2;+  uint32_t m_result;+};

src/5-async-work/async_work_thread_safe_function/napi/binding.c

new file mode 100644@@ -0,0 +1,235 @@+#include <assert.h>+#include <stdlib.h>+#define NAPI_EXPERIMENTAL+#include <node_api.h>++// Limit ourselves to this many primes, starting at 2+#define PRIME_COUNT 100000+#define REPORT_EVERY 1000++typedef struct {+  napi_async_work work;+  napi_threadsafe_function tsfn;+} AddonData;+++// This function is responsible for converting data coming in from the worker+// thread to napi_value items that can be passed into JavaScript, and for+// calling the JavaScript function.+static void CallJs(napi_env env, napi_value js_cb, void* context, void* data) {+  // This parameter is not used.+  (void) context;+  napi_status status;++  // Retrieve the prime from the item created by the worker thread.+  int the_prime = *(int*)data;++  // env and js_cb may both be NULL if Node.js is in its cleanup phase, and+  // items are left over from earlier thread-safe calls from the worker thread.+  // When env is NULL, we simply skip over the call into Javascript and free the+  // items.+  if (env != NULL) {+    napi_value undefined, js_the_prime;++    // Convert the integer to a napi_value.+    status = napi_create_int32(env, the_prime, &js_the_prime);+    assert(status == napi_ok);++    // Retrieve the JavaScript `undefined` value so we can use it as the `this`+    // value of the JavaScript function call.+    status = napi_get_undefined(env, &undefined);+    assert(status == napi_ok);++    // Call the JavaScript function and pass it the prime that the secondary+    // thread found.+    status = napi_call_function(env,+                              undefined,+                              js_cb,+                              1,+                              &js_the_prime,+                              NULL);+    assert(status == napi_ok);+  }++  // Free the item created by the worker thread.+  free(data);+}++// This function runs on a worker thread. It has no access to the JavaScript+// environment except through the thread-safe function.+static void ExecuteWork(napi_env env, void* data) {+  AddonData* addon_data = (AddonData*)data;+  int idx_inner, idx_outer;+  int prime_count = 0;+  napi_status status;++  // We bracket the use of the thread-safe function by this thread by a call to+  // napi_acquire_threadsafe_function() here, and by a call to+  // napi_release_threadsafe_function() immediately prior to thread exit.+  status = napi_acquire_threadsafe_function(addon_data->tsfn);+  assert(status == napi_ok);++  // Find the first 1000 prime numbers using an extremely inefficient algorithm.+  for (idx_outer = 2; prime_count < PRIME_COUNT; idx_outer++) {+    for (idx_inner = 2; idx_inner < idx_outer; idx_inner++) {+      if (idx_outer % idx_inner == 0) {+        break;+      }+    }+    if (idx_inner < idx_outer) {+      continue;+    }++    // We found a prime. If it's the tenth since the last time we sent one to+    // JavaScript, send it to JavaScript.+    if (!(++prime_count % REPORT_EVERY)) {++      // Save the prime number to the heap. The JavaScript marshaller (CallJs)+      // will free this item after having sent it to JavaScript.+      int* the_prime = malloc(sizeof(*the_prime));+      *the_prime = idx_outer;++      // Initiate the call into JavaScript. The call into JavaScript will not+      // have happened when this function returns, but it will be queued.+      status = napi_call_threadsafe_function(addon_data->tsfn,+                                           the_prime,+                                           napi_tsfn_blocking);+      assert(status == napi_ok);+    }+  }++  // Indicate that this thread will make no further use of the thread-safe function.+  status = napi_release_threadsafe_function(addon_data->tsfn,+                                          napi_tsfn_release);+  assert(status == napi_ok);+}++// This function runs on the main thread after `ExecuteWork` exits.+static void WorkComplete(napi_env env, napi_status status, void* data) {+  AddonData* addon_data = (AddonData*)data;++  // Clean up the thread-safe function and the work item associated with this+  // run.+  status = napi_release_threadsafe_function(addon_data->tsfn,+                                            napi_tsfn_release);+  assert(status == napi_ok);+  status = napi_delete_async_work(env, addon_data->work);+  assert(status == napi_ok);++  // Set both values to NULL so JavaScript can order a new run of the thread.+  addon_data->work = NULL;+  addon_data->tsfn = NULL;+}++// Create a thread-safe function and an async queue work item. We pass the+// thread-safe function to the async queue work item so the latter might have a+// chance to call into JavaScript from the worker thread on which the+// ExecuteWork callback runs.+static napi_value StartThread(napi_env env, napi_callback_info info) {+  size_t argc = 1;+  napi_value js_cb, work_name;+  AddonData* addon_data;+  napi_status status;++  // Retrieve the JavaScript callback we should call with items generated by the+  // worker thread, and the per-addon data.+  status = napi_get_cb_info(env,+                          info,+                          &argc,+                          &js_cb,+                          NULL,+                          (void**)(&addon_data));+  assert(status == napi_ok);++  // Ensure that no work is currently in progress.+  assert(addon_data->work == NULL && "Only one work item must exist at a time");++  // Create a string to describe this asynchronous operation.+  status = napi_create_string_utf8(env,+                                 "Node-API Thread-safe Call from Async Work Item",+                                 NAPI_AUTO_LENGTH,+                                 &work_name);+  assert(status == napi_ok);++  // Convert the callback retrieved from JavaScript into a thread-safe function+  // which we can call from a worker thread.+  status = napi_create_threadsafe_function(env,+                                         js_cb,+                                         NULL,+                                         work_name,+                                         0,+                                         1,+                                         NULL,+                                         NULL,+                                         NULL,+                                         CallJs,+                                         &(addon_data->tsfn));+  assert(status == napi_ok);++  // Create an async work item, passing in the addon data, which will give the+  // worker thread access to the above-created thread-safe function.+  status = napi_create_async_work(env,+                                NULL,+                                work_name,+                                ExecuteWork,+                                WorkComplete,+                                addon_data,+                                &(addon_data->work));+  assert(status == napi_ok);++  // Queue the work item for execution.+  status = napi_queue_async_work(env, addon_data->work);+  assert(status == napi_ok);++  // This causes `undefined` to be returned to JavaScript.+  return NULL;+}++// Free the per-addon-instance data.+static void addon_getting_unloaded(napi_env env, void* data, void* hint) {+  AddonData* addon_data = (AddonData*)data;+  assert(addon_data->work == NULL &&+      "No work item in progress at module unload");+  free(addon_data);+}++// The commented-out return type and the commented out formal function+// parameters below help us keep in mind the signature of the addon+// initialization function. We write the body as though the return value were as+// commented below and as though there were parameters passed in as commented+// below.+/*napi_value*/ NAPI_MODULE_INIT(/*napi_env env, napi_value exports*/) {+  napi_status status;+  // Define addon-level data associated with this instance of the addon.+  AddonData* addon_data = (AddonData*)malloc(sizeof(*addon_data));+  addon_data->work = NULL;++  // Define the properties that will be set on exports.+  napi_property_descriptor start_work = {+    "startThread",+    NULL,+    StartThread,+    NULL,+    NULL,+    NULL,+    napi_default,+    addon_data+  };++  // Decorate exports with the above-defined properties.+  status = napi_define_properties(env, exports, 1, &start_work);+  assert(status == napi_ok);++  // Associate the addon data with the exports object, to make sure that when+  // the addon gets unloaded our data gets freed.+  status = napi_wrap(env,+                   exports,+                   addon_data,+                   addon_getting_unloaded,+                   NULL,+                   NULL);+  assert(status == napi_ok);++  // Return the decorated exports object.+  return exports;+}

src/5-async-work/async_work_thread_safe_function/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  'targets': [+    {+      'target_name': 'binding',+      'sources': [ 'binding.c' ]+    }+  ]+}

src/5-async-work/async_work_thread_safe_function/napi/index.js

new file mode 100644@@ -0,0 +1,8 @@+// Use the "bindings" package to locate the native bindings.+const binding = require('bindings')('binding');++// Call the function "startThread" which the native bindings library exposes.+// The function accepts a callback which it will call from the worker thread and+// into which it will pass prime numbers. This callback simply prints them out.+binding.startThread((thePrime) =>+  console.log("Received prime from secondary thread: " + thePrime));

src/5-async-work/async_work_thread_safe_function/napi/package.json

new file mode 100644@@ -0,0 +1,17 @@+{+  "name": "async_work_thread_safe_function",+  "version": "0.0.0",+  "description": "Calling into JS from the thread pool",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1"+  },+  "engines": {+    "node": ">= 10.6.0"+  },+  "scripts": {+    "test": "node index.js"+  },+  "gypfile": true+}

src/5-async-work/call-js-from-async-worker-execute/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,28 @@+{+  "targets": [+    {+      "target_name": "dispatcher",+      "sources": [ "src/binding.cc" ],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'conditions': [+        ['OS=="win"', {+          "msvs_settings": {+            "VCCLCompilerTool": {+              "ExceptionHandling": 1+            }+          }+        }],+        ['OS=="mac"', {+          "xcode_settings": {+            "CLANG_CXX_LIBRARY": "libc++",+            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+            'MACOSX_DEPLOYMENT_TARGET': '10.7'+          }+        }]+      ]+    }+  ]+}

src/5-async-work/call-js-from-async-worker-execute/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,25 @@+'use strict'++const { EventEmitter } = require('node:events');+const { dispatch } = require('bindings')('dispatcher');++class Socket extends EventEmitter {+  constructor () {+    super();+    dispatch(this.emit.bind(this));+  }+}++const socket = new Socket();++socket.on('open', () => {+  console.log('opened');+});++socket.on('message', (message) => {+  console.log(`message: ${message}`);+});++socket.on('close', () => {+  console.log('closed');+});

src/5-async-work/call-js-from-async-worker-execute/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "call-js-from-async-worker-execute",+  "version": "0.0.0",+  "description": "Node.js Addons - calls JS from AsyncWorker::Execute",+  "main": "index.js",+  "private": true,+  "gypfile": true,+  "scripts": {+    "start": "node index.js"+  },+  "dependencies": {+    "node-addon-api": "*",+    "bindings": "*"+  }+}

src/5-async-work/call-js-from-async-worker-execute/node-addon-api/src/binding.cc

new file mode 100644@@ -0,0 +1,101 @@+#include <napi.h>++#include <chrono>+#include <thread>++class Dispatcher : public Napi::AsyncWorker {+ public:+  Dispatcher(Napi::Env env, Napi::Function& callback)+      : Napi::AsyncWorker(env),+        callback_(callback),+        tsfn_{+            Napi::ThreadSafeFunction::New(env, callback, "Dispatcher", 0, 1)} {}++  virtual ~Dispatcher() override { tsfn_.Release(); }++  void Execute() override {+    // Since this method executes on a thread that is different from the main+    // thread, we can't directly call into JavaScript. To trigger a call into+    // JavaScript from this thread, ThreadSafeFunction needs to be used to+    // communicate with the main thread, so that the main thread can invoke the+    // JavaScript function.++    napi_status status =+        tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {+          js_callback.Call({Napi::String::New(env, "open")});+        });+    if (status != napi_ok) {+      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");+      return;+    }++    std::this_thread::sleep_for(std::chrono::seconds(1));+    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {+      js_callback.Call(+          {Napi::String::New(env, "message"), Napi::String::New(env, "data1")});+    });+    if (status != napi_ok) {+      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");+      return;+    }++    std::this_thread::sleep_for(std::chrono::seconds(1));+    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {+      js_callback.Call(+          {Napi::String::New(env, "message"), Napi::String::New(env, "data2")});+    });+    if (status != napi_ok) {+      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");+      return;+    }++    std::this_thread::sleep_for(std::chrono::seconds(1));+    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {+      js_callback.Call(+          {Napi::String::New(env, "message"), Napi::String::New(env, "data3")});+    });+    if (status != napi_ok) {+      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");+      return;+    }++    status = tsfn_.BlockingCall([](Napi::Env env, Napi::Function js_callback) {+      js_callback.Call({Napi::String::New(env, "close")});+    });+    if (status != napi_ok) {+      SetError("Napi::ThreadSafeNapi::Function.BlockingCall() failed");+      return;+    }+  }++  void OnError(Napi::Error const& error) override {+    callback_.Call({Napi::String::New(Env(), "error"), error.Value()});+  }++ private:+  Napi::Function callback_;+  Napi::ThreadSafeFunction tsfn_;+};++void Dispatch(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();++  if (info.Length() < 1 || !info[0].IsFunction()) {+    Napi::TypeError::New(+        env, "The first argument needs to be the callback function.")+        .ThrowAsJavaScriptException();+    return;+  }++  Napi::Function callback = info[0].As<Napi::Function>();++  Dispatcher* dispatcher = new Dispatcher(env, callback);+  dispatcher->Queue();+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set("dispatch", Napi::Function::New(env, Dispatch));+  return exports;+}++NODE_API_MODULE(dispatcher, Init)

src/5-async-work/napi-asyncworker-example/node-addon-api/README.md

new file mode 100644@@ -0,0 +1,14 @@+# Node-API AsyncWorker Example++This is an example project showing how to use the Node.js Node-API AsyncWorker class++A tutorial describing this project can be found at the [Node-API Resource](https://napi.inspiredware.com/special-topics/asyncworker.html).++To build and run this program on your system, clone it to your computer and run these two commands inside your clone:++```+npm install+npm test+```++> You need to have Node 10.5.0 or later installed. \ No newline at end of file

src/5-async-work/napi-asyncworker-example/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,20 @@+{
+  'targets': [
+    {
+      'target_name': 'napi-asyncworker-example-native',
+      'sources': [ 'src/RunSimpleAsyncWorker.cc', 'src/SimpleAsyncWorker.cc' ],
+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],
+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],
+      'cflags!': [ '-fno-exceptions' ],
+      'cflags_cc!': [ '-fno-exceptions' ],
+      'xcode_settings': {
+        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
+        'CLANG_CXX_LIBRARY': 'libc++',
+        'MACOSX_DEPLOYMENT_TARGET': '10.7'
+      },
+      'msvs_settings': {
+        'VCCLCompilerTool': { 'ExceptionHandling': 1 },
+      }
+    }
+  ]
+}\ No newline at end of file

src/5-async-work/napi-asyncworker-example/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,23 @@+{+  "name": "napi-asyncworker-example",+  "description": "An example project showing how to use the Node.js Node-API AsyncWorker class",+  "version": "1.0.0",+  "main": "test/Test.js",+  "dependencies": {+    "node-addon-api": "^1.1.0"+  },+  "scripts": {+    "test": "node --napi-modules ./test/Test.js"+  },+  "gypfile": true,+  "keywords": [+    "node",+    "napi",+    "n-api",+    "async",+    "asyncworker",+    "example"+  ],+  "author": "Jim Schlight",+  "license": "MIT"+}

src/5-async-work/napi-asyncworker-example/node-addon-api/src/RunSimpleAsyncWorker.cc

new file mode 100644@@ -0,0 +1,19 @@+#include "SimpleAsyncWorker.h"
+
+Value runSimpleAsyncWorker(const CallbackInfo& info) {
+  int runTime = info[0].As<Number>();
+  Function callback = info[1].As<Function>();
+  SimpleAsyncWorker* asyncWorker = new SimpleAsyncWorker(callback, runTime);
+  asyncWorker->Queue();
+  std::string msg =
+      "SimpleAsyncWorker for " + std::to_string(runTime) + " seconds queued.";
+  return String::New(info.Env(), msg.c_str());
+};
+
+Object Init(Env env, Object exports) {
+  exports["runSimpleAsyncWorker"] = Function::New(
+      env, runSimpleAsyncWorker, std::string("runSimpleAsyncWorker"));
+  return exports;
+}
+
+NODE_API_MODULE(addon, Init)\ No newline at end of file

src/5-async-work/napi-asyncworker-example/node-addon-api/src/SimpleAsyncWorker.cc

new file mode 100644@@ -0,0 +1,17 @@+#include "SimpleAsyncWorker.h"
+#include <chrono>
+#include <thread>
+
+SimpleAsyncWorker::SimpleAsyncWorker(Function& callback, int runTime)
+    : AsyncWorker(callback), runTime(runTime){};
+
+void SimpleAsyncWorker::Execute() {
+  std::this_thread::sleep_for(std::chrono::seconds(runTime));
+  if (runTime == 4) SetError("Oops! Failed after 'working' 4 seconds.");
+};
+
+void SimpleAsyncWorker::OnOK() {
+  std::string msg = "SimpleAsyncWorker returning after 'working' " +
+                    std::to_string(runTime) + " seconds.";
+  Callback().Call({Env().Null(), String::New(Env(), msg)});
+};\ No newline at end of file

src/5-async-work/napi-asyncworker-example/node-addon-api/src/SimpleAsyncWorker.h

new file mode 100644@@ -0,0 +1,15 @@+#pragma once
+#include <napi.h>
+using namespace Napi;
+
+class SimpleAsyncWorker : public AsyncWorker {
+ public:
+  SimpleAsyncWorker(Function& callback, int runTime);
+  virtual ~SimpleAsyncWorker(){};
+
+  void Execute();
+  void OnOK();
+
+ private:
+  int runTime;
+};\ No newline at end of file

src/5-async-work/napi-asyncworker-example/node-addon-api/test/Test.js

new file mode 100644@@ -0,0 +1,18 @@+const runWorker = require('../build/Release/napi-asyncworker-example-native');
+
+let result = runWorker.runSimpleAsyncWorker(2, AsyncWorkerCompletion);
+console.log("runSimpleAsyncWorker returned '"+result+"'.");
+
+result = runWorker.runSimpleAsyncWorker(4, AsyncWorkerCompletion);
+console.log("runSimpleAsyncWorker returned '"+result+"'.");
+
+result = runWorker.runSimpleAsyncWorker(8, AsyncWorkerCompletion);
+console.log("runSimpleAsyncWorker returned '"+result+"'.");
+
+function AsyncWorkerCompletion (err, result) {
+    if (err) {
+        console.log("SimpleAsyncWorker returned an error: ", err);
+    } else {
+        console.log("SimpleAsyncWorker returned '"+result+"'.");
+    }
+};

src/6-threadsafe-function/promise-callback-demo/node-addon-api/README.md

new file mode 100644@@ -0,0 +1,7 @@+# Node-API Promise Callback Demo++To build and run this program on your system, clone it to your computer and run these two commands inside your clone:++```+npm install+```

src/6-threadsafe-function/promise-callback-demo/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,20 @@+{+  'targets': [+    {+      'target_name': 'promise-callback-demo',+      'sources': [ 'src/promise_callback_demo.cc' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'xcode_settings': {+        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+        'CLANG_CXX_LIBRARY': 'libc++',+        'MACOSX_DEPLOYMENT_TARGET': '10.7'+      },+      'msvs_settings': {+        'VCCLCompilerTool': { 'ExceptionHandling': 1 },+      }+    }+  ]+}

src/6-threadsafe-function/promise-callback-demo/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,18 @@+{+  "name": "promise-callback-demo",+  "main": "test/index.js",+  "private": true,+  "dependencies": {+    "node-addon-api": "^4.0.0"+  },+  "scripts": {+    "install": "node-gyp rebuild && node test"+  },+  "engines": {+    "node": ">= 10.16.0"+  },+  "version": "1.0.0",+  "description": "An promise callback demo",+  "author": "Node-API Team",+  "license": "ISC"+}

src/6-threadsafe-function/promise-callback-demo/node-addon-api/src/promise_callback_demo.cc

new file mode 100644@@ -0,0 +1,121 @@+#include <napi.h>+#include <future>+#include <iostream>+#include <thread>++using namespace Napi;++class PromiseCallbackDemo;+using Context = PromiseCallbackDemo;+using DataType = std::promise<std::string>;+void CallJs(Napi::Env env, Function callback, Context* context, DataType* data);+using TSFN = TypedThreadSafeFunction<Context, DataType, CallJs>;+using FinalizerDataType = void;++class PromiseCallbackDemo : public Napi::ObjectWrap<PromiseCallbackDemo> {+ public:+  PromiseCallbackDemo(const Napi::CallbackInfo&);++  static Napi::Function GetClass(Napi::Env);++  std::thread native_thread;+  TSFN tsfn;+};++void thread_entry(PromiseCallbackDemo* obj) {+  for (auto i = 0; i < 10; ++i) {+    std::promise<std::string> promise;+    auto future = promise.get_future();+    obj->tsfn.NonBlockingCall(&promise);++    // With exceptions disabled, STL calls will abort the thread, since we+    // cannot try/catch, as the calls to `std::make_exception_ptr()` will abort.+    try {+      auto result = future.get();+      std::cout << "Result from JS, call " << i << ": " << result << "\n";+    } catch (const std::exception& e) {+      std::cout << "Error from JS, call " << i << ": " << e.what() << "\n";+    }+  }+  obj->tsfn.Release();+}++void CallJs(Napi::Env env,+            Function callback,+            Context* context,+            DataType* data) {+  // Is the JavaScript environment still available to call into, eg. the TSFN is+  // not aborted+  if (env != nullptr) {+    auto jsPromise = callback.Call({}).As<Napi::Object>();+    auto then = jsPromise.Get("then").As<Function>();+    // Attach the resolve handler.+    // TODO proper error handling (add failure handler)+    then.Call(jsPromise,+              {Napi::Function::New(env,+                                   [=](const CallbackInfo& info) {+                                     auto result =+                                         info[0].As<String>().Utf8Value();+                                     data->set_value(result);+                                   }),+               Napi::Function::New(env, [=](const CallbackInfo& info) {+                 auto result = info[0].As<String>().Utf8Value();+                 data->set_exception(std::make_exception_ptr(+                     std::runtime_error("Error in jsCallback")));+               })});++  } else {+    data->set_exception(std::make_exception_ptr(+        std::runtime_error("Environment is shut down")));+  }+}++PromiseCallbackDemo::PromiseCallbackDemo(const Napi::CallbackInfo& info)+    : ObjectWrap(info) {+  Napi::Env env = info.Env();++  // Argument checking+  if (info.Length() < 1) {+    Napi::TypeError::New(env, "Wrong number of arguments")+        .ThrowAsJavaScriptException();+    return;+  }++  if (!info[0].IsFunction()) {+    Napi::TypeError::New(env, "First argument must be a function")+        .ThrowAsJavaScriptException();+    return;+  }++  // Since we are storing the std::thread on this ObjectWrap instance, we should+  // reference it so it doesn't get garbage collected, and unreference it on+  // TSFN finalize.+  Ref();++  tsfn = TSFN::New(+      env,+      info[0].As<Function>(),  // JavaScript function called asynchronously+      "PromiseCallbackDemo",   // Name+      0,                       // Unlimited queue+      1,                       // Only one thread will use this initially+      this,                    // Context+      [](Napi::Env,+         FinalizerDataType*,+         Context* ctx) {  // Finalizer used to clean threads up+        ctx->Unref();+        ctx->native_thread.join();+      });++  native_thread = std::thread(thread_entry, this);+}++Napi::Function PromiseCallbackDemo::GetClass(Napi::Env env) {+  return DefineClass(env, "PromiseCallbackDemo", {});+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports["PromiseCallbackDemo"] = PromiseCallbackDemo::GetClass(env);+  return exports;+}++NODE_API_MODULE(addon, Init)

src/6-threadsafe-function/promise-callback-demo/node-addon-api/test/index.js

new file mode 100644@@ -0,0 +1,11 @@+const { PromiseCallbackDemo } = require('../build/Release/promise-callback-demo');++let shouldFail = false;+// Resolve or reject a promise with an ISO date format after 100 milliseconds+function jsCallback() {+    return new Promise((resolve, reject) => setTimeout(() => {+        ((shouldFail = !shouldFail) ? reject : resolve)(new Date().toISOString());+    }, 100));+}++new PromiseCallbackDemo(jsCallback);

src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/addon.cc

new file mode 100644@@ -0,0 +1,106 @@+#include <chrono>+#include <thread>+#include "napi.h"++constexpr size_t ARRAY_LENGTH = 10;++// Data structure representing our thread-safe function context.+struct TsfnContext {+  TsfnContext(Napi::Env env) : deferred(Napi::Promise::Deferred::New(env)) {+    for (size_t i = 0; i < ARRAY_LENGTH; ++i) ints[i] = i;+  };++  // Native Promise returned to JavaScript+  Napi::Promise::Deferred deferred;++  // Native thread+  std::thread nativeThread;++  // Some data to pass around+  int ints[ARRAY_LENGTH];++  Napi::ThreadSafeFunction tsfn;+};++// The thread entry point. This takes as its arguments the specific+// threadsafe-function context created inside the main thread.+void threadEntry(TsfnContext* context);++// The thread-safe function finalizer callback. This callback executes+// at destruction of thread-safe function, taking as arguments the finalizer+// data and threadsafe-function context.+void FinalizerCallback(Napi::Env env, void* finalizeData, TsfnContext* context);++// Exported JavaScript function. Creates the thread-safe function and native+// thread. Promise is resolved in the thread-safe function's finalizer.+Napi::Value CreateTSFN(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();++  // Construct context data+  auto testData = new TsfnContext(env);++  // Create a new ThreadSafeFunction.+  testData->tsfn = Napi::ThreadSafeFunction::New(+      env,                           // Environment+      info[0].As<Napi::Function>(),  // JS function from caller+      "TSFN",                        // Resource name+      0,                             // Max queue size (0 = unlimited).+      1,                             // Initial thread count+      testData,                      // Context,+      FinalizerCallback,             // Finalizer+      (void*)nullptr                 // Finalizer data+  );+  testData->nativeThread = std::thread(threadEntry, testData);++  // Return the deferred's Promise. This Promise is resolved in the thread-safe+  // function's finalizer callback.+  return testData->deferred.Promise();+}++// The thread entry point. This takes as its arguments the specific+// threadsafe-function context created inside the main thread.+void threadEntry(TsfnContext* context) {+  // This callback transforms the native addon data (int *data) to JavaScript+  // values. It also receives the treadsafe-function's registered callback, and+  // may choose to call it.+  auto callback = [](Napi::Env env, Napi::Function jsCallback, int* data) {+    jsCallback.Call({Napi::Number::New(env, *data)});+  };++  for (size_t index = 0; index < ARRAY_LENGTH; ++index) {+    // Perform a call into JavaScript.+    napi_status status =+        context->tsfn.BlockingCall(&context->ints[index], callback);++    if (status != napi_ok) {+      Napi::Error::Fatal(+          "ThreadEntry",+          "Napi::ThreadSafeNapi::Function.BlockingCall() failed");+    }+    // Sleep for some time.+    std::this_thread::sleep_for(std::chrono::milliseconds(200));+  }++  // Release the thread-safe function. This decrements the internal thread+  // count, and will perform finalization since the count will reach 0.+  context->tsfn.Release();+}++void FinalizerCallback(Napi::Env env,+                       void* finalizeData,+                       TsfnContext* context) {+  // Join the thread+  context->nativeThread.join();++  // Resolve the Promise previously returned to JS via the CreateTSFN method.+  context->deferred.Resolve(Napi::Boolean::New(env, true));+  delete context;+}++// Addon entry point+Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports["createTSFN"] = Napi::Function::New(env, CreateTSFN);+  return exports;+}++NODE_API_MODULE(addon, Init)

src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/addon.js

new file mode 100644@@ -0,0 +1,9 @@+const { createTSFN } = require('bindings')('addon');++const callback = (...args) => { +    console.log(new Date, ...args); +};++void async function() {+    console.log(await createTSFN(callback));+}();

src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,21 @@+{+  'targets': [{+    'target_name': 'addon',+    'defines': ['V8_DEPRECATION_WARNINGS=1'],+    'sources': ['addon.cc'],+    'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+    'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+    'cflags!': ['-fno-exceptions'],+    'cflags_cc!': ['-fno-exceptions'],+    'xcode_settings': {+      'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+      'CLANG_CXX_LIBRARY': 'libc++',+      'MACOSX_DEPLOYMENT_TARGET': '10.7',+    },+    'msvs_settings': {+      'VCCLCompilerTool': {+        'ExceptionHandling': 1+      },+    },+  }]+}

src/6-threadsafe-function/thread_safe_function_counting/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "tsfn-counting",+  "version": "0.0.0",+  "description": "Thread-safe Function Example",+  "main": "addon.js",+  "private": true,+  "gypfile": true,+  "dependencies": {+    "node-addon-api": "*",+    "bindings": "*"+  },+  "engines": {+    "node": ">= 10.16.0"+  }+}

src/6-threadsafe-function/thread_safe_function_round_trip/napi/binding.gyp

new file mode 100644@@ -0,0 +1,8 @@+{+  'targets': [+    {+      'target_name': 'round_trip',+      'sources': [ 'round_trip.c' ]+    }+  ]+}

src/6-threadsafe-function/thread_safe_function_round_trip/napi/index.js

new file mode 100644@@ -0,0 +1,14 @@+const bindings = require('bindings')('round_trip');++bindings.startThread(item => {+  const thePrime = item.prime;+  console.log('The prime: ' + thePrime);++  // Answer the call with a 90% probability of returning true somewhere between+  // 200 and 400 ms from now.+  setTimeout(() => {+    const theAnswer = (Math.random() > 0.1);+    console.log(thePrime + ': answering with ' + theAnswer);+    bindings.registerReturnValue(item, theAnswer);+  }, Math.random() * 200 + 200);+});

src/6-threadsafe-function/thread_safe_function_round_trip/napi/package.json

new file mode 100644@@ -0,0 +1,17 @@+{+  "name": "thread_safe_function_round_trip",+  "version": "0.0.0",+  "description": "Thread-safe Function Example With JavaScript Round Trip",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1"+  },+  "engines": {+    "node": ">= 10.6.0"+  },+  "scripts": {+    "test": "node index.js"+  },+  "gypfile": true+}

src/6-threadsafe-function/thread_safe_function_round_trip/napi/round_trip.c

new file mode 100644@@ -0,0 +1,427 @@+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <uv.h>+#define NAPI_EXPERIMENTAL+#include <node_api.h>++#define CHECK(expr) \+  { \+    if ((expr) == 0) { \+      fprintf(stderr, "%s:%d: failed assertion `%s'\n", __FILE__, __LINE__, #expr); \+      fflush(stderr); \+      abort(); \+    } \+  }++#define REPORT_EVERY 1000++// An item that will be generated from the thread, passed into JavaScript, and+// ultimately marked as resolved when the JavaScript passes it back into the+// addon instance with a return value.+typedef struct ThreadItem {+  // This field is read-only once set, so it need not be protected by the mutex.+  int the_prime;++  // This field is only accessed from the secondary thread, so it also need not+  // be protected by the mutex.+  struct ThreadItem* next;++  // These two values must be protected by the mutex.+  bool call_has_returned;+  bool return_value;+} ThreadItem;++// The data associated with an instance of the addon. This takes the place of+// global static variables, while allowing multiple instances of the addon to+// co-exist.+typedef struct {+  uv_mutex_t check_status_mutex;+  uv_thread_t the_thread;+  napi_threadsafe_function tsfn;+  napi_ref thread_item_constructor;+  bool js_accepts;+} AddonData;++// This function is responsible for converting the native data coming in from+// the secondary thread to JavaScript values, and for calling the JavaScript+// function. It may also be called with `env` and `js_cb` set to `NULL` when+// Node.js is terminating and there are items coming in from the secondary+// thread left to process. In that case, this function does nothing, since it is+// the secondary thread that frees the items.+static void CallJs(napi_env env, napi_value js_cb, void* context, void* data) {+  AddonData* addon_data = (AddonData*)context;+  napi_value constructor;++  // The semantics of this example are such that, once the JavaScript returns+  // `false`, the `ThreadItem` structures can no longer be accessed, because the+  // thread terminates and frees them all. Thus, we record the instant when+  // JavaScript returns `false` by setting `addon_data->js_accepts` to `false`+  // in `RegisterReturnValue` below, and we use the value here to decide whether+  // the data coming in from the secondary thread is stale or not.+  if (addon_data->js_accepts && !(env == NULL || js_cb == NULL)) {+    napi_value undefined, js_thread_item;+    // Retrieve the JavaScript `undefined` value. This will serve as the `this`+    // value for the function call.+    CHECK(napi_get_undefined(env, &undefined) == napi_ok);++    // Retrieve the constructor for the JavaScript class from which the item+    // holding the native data will be constructed.+    CHECK(napi_get_reference_value(env,+                                    addon_data->thread_item_constructor,+                                    &constructor) == napi_ok);++    // Construct a new instance of the JavaScript class to hold the native item.+    CHECK(napi_new_instance(env,+                             constructor,+                             0,+                             NULL,+                             &js_thread_item) == napi_ok);++    // Associate the native item with the newly constructed JavaScript object.+    // We assume that the JavaScript side will eventually pass this JavaScript+    // object back to us via `RegisterReturnValue`, which will allow the+    // eventual deallocation of the native data. That's why we do not provide a+    // finalizer here.+    CHECK(napi_wrap(env, js_thread_item, data, NULL, NULL, NULL) == napi_ok);++    // Call the JavaScript function with the item as wrapped into an instance of+    // the JavaScript `ThreadItem` class and the prime.+    CHECK(napi_call_function(env,+                              undefined,+                              js_cb,+                              1,+                              &js_thread_item,+                              NULL) == napi_ok);+  }+}++// When the thread is finished we join it to prevent memory leaks. We can safely+// set `addon_data->tsfn` to NULL, because the thread-safe function will be+// cleaned up in the background in response to the secondary thread having+// called `napi_release_threadsafe_function()`.+static void ThreadFinished(napi_env env, void* data, void* context) {+  (void) context;+  AddonData* addon_data = (AddonData*)data;+  CHECK(uv_thread_join(&(addon_data->the_thread)) == 0);+  addon_data->tsfn = NULL;+}++// The secondary thread produces prime numbers using a very inefficient+// algorithm and calls into JavaScript with every REPORT_EVERYth prime number.+// After each call it checks whether any of the previous calls have produced a+// return value, and, if so, whether that return value is `false`. A `false`+// return value indicates that the JavaScript side is no longer interested in+// receiving any values and that the thread and the thread-safe function are to+// be cleaned up. On the JavaScript thread, this is marked in+// `addon_data->js_accepts`. When set to `false`, the JavaScript thread will not+// access the thread items any further, so they can be safely deleted on this+// thread.+static void PrimeThread(void* data) {+  AddonData* addon_data = (AddonData*) data;+  int idx_outer, idx_inner;+  int prime_count = 0;+  ThreadItem* first = NULL;+  ThreadItem* current = NULL;+  ThreadItem* previous = NULL;+  ThreadItem* returned = NULL;++  // Check each integer whether it's a prime.+  for (idx_outer = 2 ;; idx_outer++) {++    // Check whether `idx_outer` is divisible by anything up to and not+    // including itself.+    for (idx_inner = 2;+        idx_inner < idx_outer && idx_outer % idx_inner != 0;+        idx_inner++);++    // If we find a prime, and it is REPORT_EVERY primes away from the previous+    // prime we found, then we send it to JavaScript.+    if (idx_inner >= idx_outer && (++prime_count % REPORT_EVERY) == 0) {+      // Create a new thread item and attach it to the list of outstanding+      // `ThreadItem` structures representing calls into JavaScript for which+      // no return value has yet been established.+      current = memset(malloc(sizeof(*current)), 0, sizeof(*current));+      current->the_prime = idx_outer;+      current->call_has_returned = false;+      current->return_value = false;+      current->next = first;+      first = current;++      // Pass the new item into JavaScript.+      CHECK(napi_call_threadsafe_function(addon_data->tsfn,+                                           first,+                                           napi_tsfn_blocking) == napi_ok);+    }++    // Pass over all outstanding thread items and check whether any of them have+    // returned.+    for (current = first, previous = NULL, returned = NULL;+        current != NULL && returned == NULL;+        previous = current,+        current = current->next) {+      uv_mutex_lock(&(addon_data->check_status_mutex));+      if (current->call_has_returned) {+        // Unhook the call that has returned from the list.+        if (previous != NULL) {+          previous->next = current->next;+        } else {+          first = current->next;+        }+        returned = current;+      }+      uv_mutex_unlock(&(addon_data->check_status_mutex));+    }++    // Process a return value. Free the `ThreadItem` that returned it, and break+    // out of the loop if the return value was `false`.+    if (returned != NULL) {+      // Save the return value to a local variable because we have to check it+      // after having freed the structure wherein it is stored.+      bool return_value = returned->return_value;+      free(returned);+      if (!return_value) {+        break;+      }+    }+  }++  // Before terminating the thread we free the remaining queue items. `CallJs`+  // will be called with pointers to these items, perhaps after this thread has+  // already freed them, but that's OK, because on the JavaScript thread+  // `addon_data->js_accepts` will certainly have been set to `false`, and so+  // `CallJs` will not dereference the stale pointers.+  for (current = first; current != NULL;) {+    previous = current;+    current = current->next;+    free(previous);+  }++  // Release the thread-safe function. This causes it to be cleaned up in the+  // background.+  CHECK(napi_release_threadsafe_function(addon_data->tsfn,+                                          napi_tsfn_release) == napi_ok);+}++// This binding can be called from JavaScript to start the asynchronous prime+// generator.+static napi_value StartThread(napi_env env, napi_callback_info info) {+  size_t argc = 1;+  napi_value js_cb, work_name;+  AddonData* addon_data;++  // The binding accepts one parameter - the JavaScript callback function to+  // call.+  CHECK(napi_get_cb_info(env,+                          info,+                          &argc,+                          &js_cb,+                          NULL,+                          (void*)&addon_data) == napi_ok);++  // We do not create a second thread if one is already running.+  CHECK(addon_data->tsfn == NULL && "Work already in progress");++  addon_data->js_accepts = true;++  // This string describes the asynchronous work.+  CHECK(napi_create_string_utf8(env,+                                 "Thread-safe Function Round Trip Example",+                                 NAPI_AUTO_LENGTH,+                                 &work_name) == napi_ok);++  // The thread-safe function will be created with an unlimited queue and with+  // an initial thread count of 1. The secondary thread will release the+  // thread-safe function, decreasing its thread count to 0, thereby setting off+  // the process of cleaning up the thread-safe function.+  CHECK(napi_create_threadsafe_function(env,+                                         js_cb,+                                         NULL,+                                         work_name,+                                         0,+                                         1,+                                         addon_data,+                                         ThreadFinished,+                                         addon_data,+                                         CallJs,+                                         &addon_data->tsfn) == napi_ok);++  // Create the thread that will produce primes and that will call into+  // JavaScript using the thread-safe function.+  CHECK(uv_thread_create(&(addon_data->the_thread), PrimeThread, addon_data) == 0);++  return NULL;+}++static bool+is_thread_item (napi_env env, napi_ref constructor_ref, napi_value value) {+  bool validate;+  napi_value constructor;+  CHECK(napi_get_reference_value(env,+                                  constructor_ref,+                                  &constructor) == napi_ok);+  CHECK(napi_instanceof(env, value, constructor, &validate) == napi_ok);+  return validate;+}++// We use a separate binding to register a return value for a given call into+// JavaScript, represented by a `ThreadItem` object on both the JavaScript side+// and the native side. This allows the JavaScript side to asynchronously+// determine the return value.+static napi_value RegisterReturnValue(napi_env env, napi_callback_info info) {+  // This function accepts two parameters:+  // 1. The thread item passed into JavaScript via `CallJs`, and+  // 2. The desired return value.+  size_t argc = 2;+  napi_value argv[2];+  AddonData* addon_data;+  bool return_value;+  ThreadItem* item;++  // Retrieve the parameters with which this function was called.+  CHECK(napi_get_cb_info(env,+                          info,+                          &argc,+                          argv,+                          NULL,+                          (void*)&addon_data) == napi_ok);++  // If this function recorded a return value of `false` before, it means that+  // the thread and the associated thread-safe function are shutting down. This,+  // in turn means that the wrapped `ThreadItem` that was received in the first+  // argument may also be stale. Our best strategy is to do nothing and return+  // to JavaScript.+  if (!addon_data->js_accepts) {+    return NULL;+  }++  CHECK(argc == 2 && "Exactly two arguments were received");++  // Make sure the first parameter is an instance of the `ThreadItem` class.+  // This type check ensures that there *is* a pointer stored inside the+  // JavaScript object, and that the pointer is to a `ThreadItem` structure.+  CHECK(is_thread_item(env, addon_data->thread_item_constructor, argv[0]));++  // Retrieve the native data from the item.+  CHECK(napi_unwrap(env, argv[0], (void**)&item) == napi_ok);++  // Retrieve the desired return value.+  CHECK(napi_get_value_bool(env, argv[1], &return_value) == napi_ok);++  // Set `js_accepts` to false in case the JavaScript callback returned false.+  if (addon_data->js_accepts) {+    addon_data->js_accepts = return_value;+  }++  // Mark the thread item as resolved, and record the JavaScript return value.+  uv_mutex_lock(&(addon_data->check_status_mutex));+  item->call_has_returned = true;+  item->return_value = return_value;+  uv_mutex_unlock(&(addon_data->check_status_mutex));++  return NULL;+}++// Constructor for instances of the `ThreadItem` class. This doesn't need to do+// anything since all we want the class for is to be able to type-check+// JavaScript objects that carry within them a pointer to a native `ThreadItem`+// structure.+static napi_value ThreadItemConstructor(napi_env env, napi_callback_info info) {+  return NULL;+}++// Getter for the `prime` property of the `ThreadItem` class.+static napi_value GetPrime(napi_env env, napi_callback_info info) {+  napi_value jsthis, prime_property;+  AddonData* ad;+  CHECK(napi_ok == napi_get_cb_info(env, info, 0, 0, &jsthis, (void*)&ad));+  CHECK(is_thread_item(env, ad->thread_item_constructor, jsthis));+  ThreadItem* item;+  CHECK(napi_ok == napi_unwrap(env, jsthis, (void**)&item));+  CHECK(napi_ok == napi_create_int32(env, item->the_prime, &prime_property));+  return prime_property;+}++static void addon_is_unloading(napi_env env, void* data, void* hint) {+  AddonData* addon_data = (AddonData*)data;+  uv_mutex_destroy(&(addon_data->check_status_mutex));+  CHECK(napi_delete_reference(env,+                               addon_data->thread_item_constructor) == napi_ok);+  free(data);+}++// Initialize an instance of this addon. This function may be called multiple+// times if multiple instances of Node.js are running on multiple threads, or if+// there are multiple Node.js contexts running on the same thread. The return+// value and the formal parameters in comments remind us that the function body+// that follows, within which we initialize the addon, has available to it the+// variables named in the formal parameters, and that it must return a+// `napi_value`.+/*napi_value*/ NAPI_MODULE_INIT(/*napi_env env, napi_value exports*/) {+  // Create the native data that will be associated with this instance of the+  // addon.+  AddonData* addon_data =+      memset(malloc(sizeof(*addon_data)), 0, sizeof(*addon_data));++  // Attach the addon data to the exports object to ensure that they are+  // destroyed together.+  CHECK(napi_wrap(env,+                   exports,+                   addon_data,+                   addon_is_unloading,+                   NULL,+                   NULL) == napi_ok);++  // Initialize the various members of the `AddonData` associated with this+  // addon instance.+  CHECK(uv_mutex_init(&(addon_data->check_status_mutex)) == 0);++  napi_value thread_item_class;+  napi_property_descriptor thread_item_properties[] = {+    { "prime", 0, 0, GetPrime, 0, 0, napi_enumerable, addon_data }+  };+  CHECK(napi_define_class(env,+                           "ThreadItem",+                           NAPI_AUTO_LENGTH,+                           ThreadItemConstructor,+                           addon_data,+                           1,+                           thread_item_properties,+                           &thread_item_class) == napi_ok);+  CHECK(napi_create_reference(env,+                               thread_item_class,+                               1,+                               &(addon_data->thread_item_constructor)) ==+                                  napi_ok);++  // Expose the two bindings this addon provides.+  napi_property_descriptor export_properties[] = {+    {+      "startThread",+      NULL,+      StartThread,+      NULL,+      NULL,+      NULL,+      napi_default,+      addon_data+    },+    {+      "registerReturnValue",+      NULL,+      RegisterReturnValue,+      NULL,+      NULL,+      NULL,+      napi_default,+      addon_data+    }+  };+  CHECK(napi_define_properties(env,+                                exports,+                                sizeof(export_properties) /+                                    sizeof(export_properties[0]),+                                export_properties) == napi_ok);++  return exports;+}

src/6-threadsafe-function/thread_safe_function_with_object_wrap/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,17 @@+{+  "targets": [+    {+      "target_name": "tsfn_object_wrap",+      "sources": [+        "tsfn_object_wrap.cc",+      ],+      "defines": [+        "NAPI_DISABLE_CPP_EXCEPTIONS",+        "NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS"+      ],+      "include_dirs": [+        "<!@(node -p \"require('node-addon-api').include\")"+      ],+    }+  ]+}

src/6-threadsafe-function/thread_safe_function_with_object_wrap/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,11 @@+{+  "name": "tsfn-test",+  "version": "1.0.0",+  "description": "",+  "main": "index.js",+  "author": "",+  "dependencies": {+    "bindings": "*",+    "node-addon-api": "^7.0.0"+  }+}

src/6-threadsafe-function/thread_safe_function_with_object_wrap/node-addon-api/tsfn_object_wrap.cc

new file mode 100644@@ -0,0 +1,77 @@+#include <inttypes.h>+#include <napi.h>+#include <thread>++// A secondary thread increments a value starting from 0 and calls a JS callback+// on the JavaScript main thread.++// The ObjectWrap subclass whose instances own such a secondary thread.+class TsfnObjectWrap : public Napi::ObjectWrap<TsfnObjectWrap> {+ public:+  static Napi::Object Init(Napi::Env env) {+    return DefineClass(env, "TsfnObjectWrap", {});+  }++  TsfnObjectWrap(const Napi::CallbackInfo& info)+      : Napi::ObjectWrap<TsfnObjectWrap>(info) {+    // Whenever we construct a new instance of type TsfnObjectWrap, we construct+    // a thread-safe function that can be called from a secondary thread and+    // which provides a value to the JavaScript main thread.+    _tsfn = Napi::ThreadSafeFunction::New(+        info.Env(), info[0].As<Napi::Function>(), "TsfnObjectWrap", 1, 2);++    _thread = std::thread(&TsfnObjectWrap::Thread, std::ref(_tsfn));+  }++  ~TsfnObjectWrap() {+    _tsfn.Abort();+    _thread.join();+  }++ private:+  // This is the secondary thread.+  static void Thread(const Napi::ThreadSafeFunction& tsfn) {+    int64_t the_value = 0;+    int64_t buffer[3] = {0, 0, 0};+    int idx = 0;++    // Since we're calling the JavaScript main thread in a blocking fashion,+    // a buffer of three values is sufficient for synchronizing with the main+    // thread without losing a single value and without having to allocate an+    // integer on the heap for each call into JavaScript.+    while (true) {+      buffer[idx] = the_value;+      idx = (idx + 1) % 3;+      int64_t* value_ref = &buffer[idx];+      napi_status status = tsfn.BlockingCall(+          value_ref, [](Napi::Env env, Napi::Function fn, int64_t* data) {+            int64_t native_value = *data;+            Napi::Value result =+                fn.Call({Napi::Number::New(env, native_value)});+            if (result.IsEmpty()) {+              printf("main with %" PRId64 ": result was empty!\n",+                     native_value);+            } else {+              printf("main with %" PRId64 ": Done!\n",+                     result.As<Napi::Number>().Int64Value());+            }+          });+      // We break out of the infinite loop when we're informed that the thread-+      // safe function is being torn down.+      if (status == napi_closing) {+        break;+      }+      the_value++;+    }+  }++  Napi::ThreadSafeFunction _tsfn;+  std::thread _thread;+};++// Boilerplate code to define an add-on that consists of the above class.+Napi::Object TsfnObjectWrapExampleInit(Napi::Env env, Napi::Object exports) {+  return TsfnObjectWrap::Init(env);+}++NODE_API_MODULE(TsfnObjectWrapExample, TsfnObjectWrapExampleInit)

src/6-threadsafe-function/thread_safe_function_with_object_wrap/node-addon-api/tsfn_object_wrap.js

new file mode 100644@@ -0,0 +1,18 @@+const TsfnObjectWrap = require('bindings')('tsfn_object_wrap.node')+const x = new TsfnObjectWrap((value) => {+  // Do something, anything, with x to keep it in scope, otherwise the instance+  // will be collected and the process will exit.+  x.someProperty = value;++  console.log('JS1: Called with ' + value);+  return -value;+});++const y = new TsfnObjectWrap((value) => {+  // Do something, anything, with y to keep it in scope, otherwise the instance+  // will be collected and the process will exit.+  y.someProperty = value;++  console.log('JS2: Called with ' + value);+  return -value;+});

src/6-threadsafe-function/threadsafe-async-iterator/node-addon-api/CMakeLists.txt

new file mode 100644@@ -0,0 +1,23 @@+project (example)+include_directories(${CMAKE_JS_INC} node_modules/node-addon-api/)+cmake_minimum_required(VERSION 3.18)++set(CMAKE_CXX_STANDARD 20)+set(CMAKE_CXX_STANDARD_REQUIRED ON)+include_directories(${CMAKE_JS_INC})+file(GLOB SOURCE_FILES "*.cc")+add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")+target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})++# Include Node-API wrappers+execute_process(COMMAND node -p "require('node-addon-api').include"+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}+        OUTPUT_VARIABLE NODE_ADDON_API_DIR+        )+string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})++target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})++# define NAPI_VERSION+add_definitions(-DNAPI_VERSION=6)

src/6-threadsafe-function/threadsafe-async-iterator/node-addon-api/example.cc

new file mode 100644@@ -0,0 +1,163 @@+#include <napi.h>+#include <condition_variable>+#include <functional>+#include <memory>+#include <mutex>+#include <optional>+#include <thread>++using namespace Napi;++class ThreadSafeAsyncIteratorExample+    : public ObjectWrap<ThreadSafeAsyncIteratorExample> {+ public:+  ThreadSafeAsyncIteratorExample(const CallbackInfo& info)+      : ObjectWrap<ThreadSafeAsyncIteratorExample>(info),+        _current(info[0].As<Number>()),+        _last(info[1].As<Number>()) {}++  static Object Init(Napi::Env env, Napi::Object exports);++  Napi::Value Iterator(const CallbackInfo& info);++ private:+  using Context = ThreadSafeAsyncIteratorExample;++  struct DataType {+    std::unique_ptr<Promise::Deferred> deferred;+    bool done;+    std::optional<int> value;+  };++  static void CallJs(Napi::Env env,+                     Function callback,+                     Context* context,+                     DataType* data);++  using TSFN = TypedThreadSafeFunction<Context, DataType, CallJs>;++  using FinalizerDataType = void;++  int _current;+  int _last;+  TSFN _tsfn;+  std::thread _thread;+  std::unique_ptr<Promise::Deferred> _deferred;++  // Thread-safety+  std::mutex _mtx;+  std::condition_variable _cv;++  void threadEntry();++  static void FinalizerCallback(Napi::Env env,+                                void*,+                                ThreadSafeAsyncIteratorExample* context);+};++Object ThreadSafeAsyncIteratorExample::Init(Napi::Env env,+                                            Napi::Object exports) {+  Napi::Function func =+      DefineClass(env,+                  "ThreadSafeAsyncIteratorExample",+                  {InstanceMethod(Napi::Symbol::WellKnown(env, "asyncIterator"),+                                  &ThreadSafeAsyncIteratorExample::Iterator)});++  exports.Set("ThreadSafeAsyncIteratorExample", func);+  return exports;+}++Napi::Value ThreadSafeAsyncIteratorExample::Iterator(const CallbackInfo& info) {+  auto env = info.Env();++  if (_thread.joinable()) {+    Napi::Error::New(env, "Concurrent iterations not implemented.")+        .ThrowAsJavaScriptException();+    return Napi::Value();+  }++  _tsfn =+      TSFN::New(info.Env(),+                "tsfn",+                0,+                1,+                this,+                std::function<decltype(FinalizerCallback)>(FinalizerCallback));++  // To prevent premature garbage collection; Unref in TFSN finalizer+  Ref();++  // Create thread+  _thread = std::thread(&ThreadSafeAsyncIteratorExample::threadEntry, this);++  // Create iterable+  auto iterable = Napi::Object::New(env);++  iterable["next"] =+      Function::New(env, [this](const CallbackInfo& info) -> Napi::Value {+        std::lock_guard<std::mutex> lk(_mtx);+        auto env = info.Env();+        if (_deferred) {+          Napi::Error::New(env, "Concurrent iterations not implemented.")+              .ThrowAsJavaScriptException();+          return Napi::Value();+        }+        _deferred = std::make_unique<Promise::Deferred>(env);+        _cv.notify_all();+        return _deferred->Promise();+      });++  return iterable;+}++void ThreadSafeAsyncIteratorExample::threadEntry() {+  while (true) {+    std::unique_lock<std::mutex> lk(_mtx);+    _cv.wait(lk, [this] { return this->_deferred != nullptr; });+    auto done = _current > _last;+    if (done) {+      _tsfn.BlockingCall(new DataType{std::move(this->_deferred), true, {}});+      break;+    } else {+      std::this_thread::sleep_for(+          std::chrono::seconds(1));  // Simulate CPU-intensive work+      _tsfn.BlockingCall(+          new DataType{std::move(this->_deferred), false, _current++});+    }+  }+  _tsfn.Release();+}++void ThreadSafeAsyncIteratorExample::CallJs(Napi::Env env,+                                            Function callback,+                                            Context* context,+                                            DataType* data) {+  if (env != nullptr) {+    auto value = Object::New(env);++    if (data->done) {+      value["done"] = Boolean::New(env, true);+    } else {+      value["done"] = Boolean::New(env, false);+      value["value"] = Number::New(env, data->value.value());+    }+    data->deferred->Resolve(value);+  }++  if (data != nullptr) {+    delete data;+  }+}++void ThreadSafeAsyncIteratorExample::FinalizerCallback(+    Napi::Env env, void*, ThreadSafeAsyncIteratorExample* context) {+  context->_thread.join();+  context->Unref();+}++Napi::Object Init(Napi::Env env, Object exports) {+  ThreadSafeAsyncIteratorExample::Init(env, exports);+  return exports;+}++NODE_API_MODULE(example, Init)

src/6-threadsafe-function/threadsafe-async-iterator/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,14 @@+const { ThreadSafeAsyncIteratorExample } = require('bindings')('example');++async function main(from, to) {+    const iterator = new ThreadSafeAsyncIteratorExample(from, to);+    for await (const value of iterator) {+        console.log(value);+    }+}++main(0, 5)+    .catch(e => {+        console.error(e);+        process.exit(1);+    });

src/6-threadsafe-function/threadsafe-async-iterator/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,16 @@+{+  "name": "threadsafe-async-iterator-example",+  "version": "0.0.0",+  "description": "Async iterator example with threadsafe functions using node-addon-api",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "^1.5.0",+    "cmake-js": "^6.3.0",+    "node-addon-api": "^5.0.0"+  },+  "scripts": {+    "test": "node index.js",+    "install": "cmake-js compile"+  }+}

src/6-threadsafe-function/typed_threadsafe_function/node-addon-api/CMakeLists.txt

new file mode 100644@@ -0,0 +1,23 @@+project (clock)+include_directories(${CMAKE_JS_INC} node_modules/node-addon-api/)+cmake_minimum_required(VERSION 3.18)++set(CMAKE_CXX_STANDARD 20)+set(CMAKE_CXX_STANDARD_REQUIRED ON)+include_directories(${CMAKE_JS_INC})+file(GLOB SOURCE_FILES "*.cc")+add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")+target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})++# Include Node-API wrappers+execute_process(COMMAND node -p "require('node-addon-api').include"+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}+        OUTPUT_VARIABLE NODE_ADDON_API_DIR+        )+string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})++target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})++# define NAPI_VERSION+add_definitions(-DNAPI_VERSION=4)

src/6-threadsafe-function/typed_threadsafe_function/node-addon-api/clock.cc

new file mode 100644@@ -0,0 +1,97 @@+#include <napi.h>+#include <chrono>+#include <thread>++using namespace Napi;++using Context = Reference<Value>;+using DataType = int;+void CallJs(Napi::Env env, Function callback, Context* context, DataType* data);+using TSFN = TypedThreadSafeFunction<Context, DataType, CallJs>;+using FinalizerDataType = void;++std::thread nativeThread;+TSFN tsfn;++Value Start(const CallbackInfo& info) {+  Napi::Env env = info.Env();++  if (info.Length() < 2) {+    throw TypeError::New(env, "Expected two arguments");+  } else if (!info[0].IsFunction()) {+    throw TypeError::New(env, "Expected first arg to be function");+  } else if (!info[1].IsNumber()) {+    throw TypeError::New(env, "Expected second arg to be number");+  }++  int count = info[1].As<Number>().Int32Value();++  // Create a new context set to the the receiver (ie, `this`) of the function+  // call+  Context* context = new Reference<Value>(Persistent(info.This()));++  // Create a ThreadSafeFunction+  tsfn = TSFN::New(+      env,+      info[0].As<Function>(),  // JavaScript function called asynchronously+      "Resource Name",         // Name+      0,                       // Unlimited queue+      1,                       // Only one thread will use this initially+      context,+      [](Napi::Env,+         FinalizerDataType*,+         Context* ctx) {  // Finalizer used to clean threads up+        nativeThread.join();+        delete ctx;+      });++  // Create a native thread+  nativeThread = std::thread([count] {+    for (int i = 0; i < count; i++) {+      // Create new data+      int* value = new int(clock());++      // Perform a blocking call+      napi_status status = tsfn.BlockingCall(value);+      if (status != napi_ok) {+        // Handle error+        break;+      }++      std::this_thread::sleep_for(std::chrono::seconds(1));+    }++    // Release the thread-safe function+    tsfn.Release();+  });++  return Boolean::New(env, true);+}++// Transform native data into JS data, passing it to the provided+// `callback` -- the TSFN's JavaScript function.+void CallJs(Napi::Env env,+            Function callback,+            Context* context,+            DataType* data) {+  // Is the JavaScript environment still available to call into, eg. the TSFN is+  // not aborted+  if (env != nullptr) {+    // On Node-API 5+, the `callback` parameter is optional; however, this+    // example does ensure a callback is provided.+    if (callback != nullptr) {+      callback.Call(context->Value(), {Number::New(env, *data)});+    }+  }+  if (data != nullptr) {+    // We're finished with the data.+    delete data;+  }+}++Napi::Object Init(Napi::Env env, Object exports) {+  exports.Set("start", Function::New(env, Start));+  return exports;+}++NODE_API_MODULE(clock, Init)

src/6-threadsafe-function/typed_threadsafe_function/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,6 @@+const { start } = require('bindings')('clock');++start.call(new Date(), function (clock) {+    const context = this;+    console.log(context, clock);+}, 5);

src/6-threadsafe-function/typed_threadsafe_function/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,17 @@+{+  "name": "example-typedthreadsafefunction",+  "version": "0.0.0",+  "description": "node-addon-api TypedThreadSafeFunction example",+  "main": "index.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "cmake-js": "^6.1.0",+    "node-addon-api": "^4.0.0"+  },+  "scripts": {+    "test": "node index.js",+    "install": "cmake-js compile"+  },+  "gypfile": true+}

src/7-events/emit_event_from_cpp/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,30 @@+{+  "targets": [+    {+      "target_name": "emit_from_cpp",+      "sources": [+        "src/emit-from-cpp.cc"+      ],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'conditions': [+        ['OS=="win"', {+          "msvs_settings": {+            "VCCLCompilerTool": {+              "ExceptionHandling": 1+            }+          }+        }],+        ['OS=="mac"', {+          "xcode_settings": {+            "CLANG_CXX_LIBRARY": "libc++",+            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+            'MACOSX_DEPLOYMENT_TARGET': '10.7'+          }+        }]+      ]+    }+  ]+}

src/7-events/emit_event_from_cpp/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,19 @@+'use strict'++const EventEmitter = require('events').EventEmitter+const addon = require('bindings')('emit_from_cpp')++const emitter = new EventEmitter()++emitter.on('start', () => {+    console.log('### START ...')+})+emitter.on('data', (evt) => {+    console.log(evt);+})++emitter.on('end', () => {+    console.log('### END ###')+})++addon.callEmit(emitter.emit.bind(emitter))

src/7-events/emit_event_from_cpp/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "emit-event-from-cpp-example",+  "version": "0.0.0",+  "description": "Node.js Addons - emit event from C++ to JS",+  "main": "index.js",+  "private": true,+  "gypfile": true,+  "scripts": {+    "start": "node index.js"+  },+  "dependencies": {+    "node-addon-api": "*",+    "bindings": "*"+  }+}

src/7-events/emit_event_from_cpp/node-addon-api/src/emit-from-cpp.cc

new file mode 100644@@ -0,0 +1,27 @@+#include <napi.h>++#include <chrono>+#include <iostream>+#include <thread>++Napi::Value CallEmit(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  Napi::Function emit = info[0].As<Napi::Function>();+  emit.Call({Napi::String::New(env, "start")});+  for (int i = 0; i < 3; i++) {+    std::this_thread::sleep_for(std::chrono::seconds(3));+    emit.Call(+        {Napi::String::New(env, "data"), Napi::String::New(env, "data ...")});+  }+  emit.Call({Napi::String::New(env, "end")});+  return Napi::String::New(env, "OK");+}++// Init+Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "callEmit"),+              Napi::Function::New(env, CallEmit));+  return exports;+}++NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);

src/7-events/inherits_from_event_emitter/node-addon-api/binding.gyp

new file mode 100644@@ -0,0 +1,31 @@+{+  "targets": [+    {+      "target_name": "native_emitter",+      "sources": [+        "src/binding.cc",+        "src/native-emitter.cc"+      ],+      'cflags!': [ '-fno-exceptions' ],+      'cflags_cc!': [ '-fno-exceptions' ],+      'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],+      'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],+      'conditions': [+        ['OS=="win"', {+          "msvs_settings": {+            "VCCLCompilerTool": {+              "ExceptionHandling": 1+            }+          }+        }],+        ['OS=="mac"', {+          "xcode_settings": {+            "CLANG_CXX_LIBRARY": "libc++",+            'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',+            'MACOSX_DEPLOYMENT_TARGET': '10.7'+          }+        }]+      ]+    }+  ]+}

src/7-events/inherits_from_event_emitter/node-addon-api/index.js

new file mode 100644@@ -0,0 +1,23 @@+'use strict'++const EventEmitter = require('events').EventEmitter+const NativeEmitter = require('bindings')('native_emitter').NativeEmitter+const inherits = require('util').inherits++inherits(NativeEmitter, EventEmitter)++const emitter = new NativeEmitter()++emitter.on('start', () => {+    console.log('### START ...')+})++emitter.on('data', (evt) => {+    console.log(evt)+})++emitter.on('end', () => {+    console.log('### END ###')+})++emitter.callAndEmit()

src/7-events/inherits_from_event_emitter/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "inherits-from-event-emitter-example",+  "version": "0.0.0",+  "description": "Node.js Addons - inherits from event emitter",+  "main": "index.js",+  "private": true,+  "gypfile": true,+  "scripts": {+    "start": "node index.js"+  },+  "dependencies": {+    "node-addon-api": "*",+    "bindings": "*"+  }+}

src/7-events/inherits_from_event_emitter/node-addon-api/src/binding.cc

new file mode 100644@@ -0,0 +1,9 @@+#include <napi.h>+#include "native-emitter.h"++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  NativeEmitter::Init(env, exports);+  return exports;+}++NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

src/7-events/inherits_from_event_emitter/node-addon-api/src/native-emitter.cc

new file mode 100644@@ -0,0 +1,40 @@+#include <chrono>+#include <iostream>+#include <thread>++#include "native-emitter.h"++Napi::FunctionReference NativeEmitter::constructor;++Napi::Object NativeEmitter::Init(Napi::Env env, Napi::Object exports) {+  Napi::Function func =+      DefineClass(env,+                  "NativeEmitter",+                  {InstanceMethod("callAndEmit", &NativeEmitter::CallAndEmit)});++  constructor = Napi::Persistent(func);+  constructor.SuppressDestruct();++  exports.Set("NativeEmitter", func);+  return exports;+}++NativeEmitter::NativeEmitter(const Napi::CallbackInfo& info)+    : Napi::ObjectWrap<NativeEmitter>(info) {+  // NOOP+}++Napi::Value NativeEmitter::CallAndEmit(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  Napi::Function emit =+      info.This().As<Napi::Object>().Get("emit").As<Napi::Function>();+  emit.Call(info.This(), {Napi::String::New(env, "start")});+  for (int i = 0; i < 3; i++) {+    std::this_thread::sleep_for(std::chrono::seconds(1));+    emit.Call(+        info.This(),+        {Napi::String::New(env, "data"), Napi::String::New(env, "data ...")});+  }+  emit.Call(info.This(), {Napi::String::New(env, "end")});+  return Napi::String::New(env, "OK");+}

src/7-events/inherits_from_event_emitter/node-addon-api/src/native-emitter.h

new file mode 100644@@ -0,0 +1,12 @@+#include <napi.h>++class NativeEmitter : public Napi::ObjectWrap<NativeEmitter> {+ public:+  static Napi::Object Init(Napi::Env env, Napi::Object exports);+  NativeEmitter(const Napi::CallbackInfo& info);++ private:+  static Napi::FunctionReference constructor;++  Napi::Value CallAndEmit(const Napi::CallbackInfo& info);+};

src/8-tooling/build_with_cmake/README.md

new file mode 100644@@ -0,0 +1,33 @@+## Building Node-API Addons Using CMake.js++### Examples++The objective of these examples is to demonstrate how to build Node-API addons using [CMake.js](https://github.com/cmake-js/cmake-js#readme).++These example projects assume that CMake.js has been installed globally:++```+npm install -g cmake-js+cmake-js --help+```++Then, in each of the `napi` and `node-addon-api` directories, the following commands build and test each addon:++```+npm install+npm test+```++Complete CMake.js documentation can be found on the [CMake.js GitHub repository](https://github.com/cmake-js/cmake-js#readme).++### NAPI_VERSION++When building Node-API addons, it's important to specify to the build system the Node-API version your code is designed to work with. With CMake.js, this information is specified in the `CMakeLists.txt` file:  ++```+add_definitions(-DNAPI_VERSION=3)+```++Since Node-API is ABI-stable, your Node-API addon will work, without recompilation, with the Node-API version you specify in `NAPI_VERSION` and all subsequent Node-API versions. ++In the absence of a need for features available only in a specific Node-API version, version 3 is a good choice as it is the version of Node-API that was active when Node-API left experimental status. \ No newline at end of file

src/8-tooling/build_with_cmake/napi/CMakeLists.txt

new file mode 100644@@ -0,0 +1,13 @@+cmake_minimum_required(VERSION 3.9)+cmake_policy(SET CMP0042 NEW)+set (CMAKE_CXX_STANDARD 11)++project (build-napi-with-cmake)+include_directories(${CMAKE_JS_INC})+file(GLOB SOURCE_FILES "hello.c")+add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")+target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})++# Define NAPI_VERSION+add_definitions(-DNAPI_VERSION=3)

src/8-tooling/build_with_cmake/napi/hello.c

new file mode 100644@@ -0,0 +1,23 @@+#include <assert.h>+#include <node_api.h>++static napi_value Method(napi_env env, napi_callback_info info) {+  napi_status status;+  napi_value world;+  status = napi_create_string_utf8(env, "Hello, world!", 13, &world);+  assert(status == napi_ok);+  return world;+}++#define DECLARE_NAPI_METHOD(name, func)                                        \+  { name, 0, func, 0, 0, 0, napi_default, 0 }++static napi_value Init(napi_env env, napi_value exports) {+  napi_status status;+  napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);+  status = napi_define_properties(env, exports, 1, &desc);+  assert(status == napi_ok);+  return exports;+}++NAPI_MODULE(hello, Init)

src/8-tooling/build_with_cmake/napi/hello.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('build-napi-with-cmake');++console.log(addon.hello()); // 'world'

src/8-tooling/build_with_cmake/napi/package.json

new file mode 100644@@ -0,0 +1,14 @@+{+  "name": "build-napi-with-cmake",+  "version": "0.0.0",+  "description": "Build Node-API native addon with CMake.",+  "main": "hello.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1"+  },+  "scripts": {+    "install": "cmake-js compile",+    "test": "node hello.js"+  }+}

src/8-tooling/build_with_cmake/node-addon-api/CMakeLists.txt

new file mode 100644@@ -0,0 +1,22 @@+cmake_minimum_required(VERSION 3.9)+cmake_policy(SET CMP0042 NEW)+set (CMAKE_CXX_STANDARD 11)++project (build-node-addon-api-with-cmake)+include_directories(${CMAKE_JS_INC})+file(GLOB SOURCE_FILES "hello.cc")+add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")+target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})++# Include Node-API wrappers+execute_process(COMMAND node -p "require('node-addon-api').include"+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}+        OUTPUT_VARIABLE NODE_ADDON_API_DIR+        )+string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})++target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})++# define NAPI_VERSION+add_definitions(-DNAPI_VERSION=3)

src/8-tooling/build_with_cmake/node-addon-api/hello.cc

new file mode 100644@@ -0,0 +1,23 @@+#include <napi.h>++static Napi::String Method(const Napi::CallbackInfo& info) {+  // Napi::Env is the opaque data structure containing the environment in which+  // the request is being run. We will need this env when we want to create any+  // new objects inside of the node.js environment+  Napi::Env env = info.Env();++  // Create a C++ level variable+  std::string helloWorld = "Hello, world!";++  // Return a new javascript string that we copy-construct inside of the node.js+  // environment+  return Napi::String::New(env, helloWorld);+}++static Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "hello"),+              Napi::Function::New(env, Method));+  return exports;+}++NODE_API_MODULE(hello, Init)

src/8-tooling/build_with_cmake/node-addon-api/hello.js

new file mode 100644@@ -0,0 +1,3 @@+var addon = require('bindings')('build-node-addon-api-with-cmake');++console.log(addon.hello()); // 'world'

src/8-tooling/build_with_cmake/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,15 @@+{+  "name": "build-node-addon-api-with-cmake",+  "version": "0.0.0",+  "description": "Build Node-API native addon with CMake and node-addon-api C++ wrapper.",+  "main": "hello.js",+  "private": true,+  "dependencies": {+    "bindings": "~1.2.1",+    "node-addon-api": "^1.0.0"+  },+  "scripts": {+    "install": "cmake-js compile",+    "test": "node hello.js"+  }+}

src/8-tooling/typescript_with_addon/node-addon-api/CMakeLists.txt

new file mode 100644@@ -0,0 +1,26 @@+cmake_minimum_required(VERSION 3.9)+set (CMAKE_CXX_STANDARD 11)++project(typescript_with_addon VERSION 0.0.1)+include_directories(${CMAKE_JS_INC})+string(APPEND CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wendif-labels")++file(GLOB SOURCE_FILES *.cpp *.h *.cc *.c)+add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")+target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})++# Include Node-API wrappers+execute_process(COMMAND node -p "require('node-addon-api').include"+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}+        OUTPUT_VARIABLE NODE_ADDON_API_DIR+        )++# need to pay attention to this part+string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})++target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})++# Define NAPI_VERSION+add_definitions(-DNAPI_VERSION=3)+

src/8-tooling/typescript_with_addon/node-addon-api/README.md

new file mode 100644@@ -0,0 +1,19 @@+## TypeScript calls JavaScript that calls C++ that calls C function++### Build and run:++```+npm install +npm test+```++The result:++```+This is a TypeScript class constructor.+This is a Javascript function.+This is a C++ function.+This is a C function.+```++This is using cmake and cmake-js based on the example [build_with_cmake](../build_with_cmake)\ No newline at end of file

src/8-tooling/typescript_with_addon/node-addon-api/cPart.c

new file mode 100644@@ -0,0 +1,8 @@+#include <stdio.h>+#include "cPart.h"++int cPart(int value) {+  int newValue = value + 30;+  printf("I'm a C function and I received %d from C++ and I'm sending back %d \n",value,newValue);+  return newValue;+}\ No newline at end of file

src/8-tooling/typescript_with_addon/node-addon-api/cPart.h

new file mode 100644@@ -0,0 +1,14 @@+#ifndef _C_PART_H_+#define _C_PART_H_++#ifdef __cplusplus+extern "C" {+#endif++int cPart(int);++#ifdef __cplusplus+}  // extern "C"+#endif++#endif

src/8-tooling/typescript_with_addon/node-addon-api/cppPart.cpp

new file mode 100644@@ -0,0 +1,11 @@+#include <iostream>+#include "cPart.h"++using namespace std;++int callingCPart(int value) {+  int result = cPart(++value);+  cout << "I'm a C++ function I'm sending " << value << " to C "+       << "and I received " << result << endl;+  return result;+}\ No newline at end of file

src/8-tooling/typescript_with_addon/node-addon-api/index.ts

new file mode 100644@@ -0,0 +1,11 @@+import {javascriptPart} from './jsPart';++class TypeScriptPart {+  constructor(value:number) {+    console.log('I\'m a TypeScript class constructor I\'m sending',+    value,+    'to JavaScript and I received', javascriptPart(value));+  }+}++new TypeScriptPart(10);\ No newline at end of file

src/8-tooling/typescript_with_addon/node-addon-api/jsPart.js

new file mode 100644@@ -0,0 +1,16 @@+const addon = require('bindings')('typescript_with_addon');++function javascriptPart (value) {+  const result = addon.cppPartExportedByNapi(++value);++  console.log('I\'m a Javascript function and I\'m sending', +  value,+  'to C++ and I received',+  result);++  return result;+}++module.exports = {+  javascriptPart+}\ No newline at end of file

src/8-tooling/typescript_with_addon/node-addon-api/napiPart.cpp

new file mode 100644@@ -0,0 +1,18 @@+#include <napi.h>++extern int callingCPart(int value);++Napi::Value Method(const Napi::CallbackInfo& info) {+  Napi::Env env = info.Env();+  int value = info[0].As<Napi::Number>().Int32Value();+  Napi::Number num = Napi::Number::New(env, callingCPart(value));+  return num;+}++Napi::Object Init(Napi::Env env, Napi::Object exports) {+  exports.Set(Napi::String::New(env, "cppPartExportedByNapi"),+              Napi::Function::New(env, Method));+  return exports;+}++NODE_API_MODULE(cppPartExportedByNapi, Init)\ No newline at end of file

src/8-tooling/typescript_with_addon/node-addon-api/package.json

new file mode 100644@@ -0,0 +1,17 @@+{+  "name": "typescript_with_addon",+  "version": "0.0.0",+  "description": "TypeScript calling Javascript calling C++ calling C with building with CMake and node-addon-api C++ wrapper.",+  "dependencies": {+    "bindings": "^1.5.0",+    "node-addon-api": "^3.0.2"+  },+  "scripts": {+    "install": "npx cmake-js compile",+    "test": "ts-node index.ts"+  },+  "devDependencies": {+    "ts-node": "^9.0.0",+    "typescript": "^5.2.2"+  }+}

src/8-tooling/typescript_with_addon/node-addon-api/tsconfig.json

new file mode 100644@@ -0,0 +1,7 @@+{+  "compilerOptions": {+    "moduleResolution": "node",+    "module": "commonjs"+  }+}+

test_all.js

@@ -1,49 +1,90 @@-const fs = require('fs')-const path = require('path')-const { execSync } = require('child_process')-const chalk = require('chalk')-const semver = require('semver')--const excludeFolder = ['node_modules', 'website']--function getAllTests() {-  return fs-    .readdirSync('./')-    .filter(i => {-      return (-        !i.startsWith('.') &&-        fs.statSync(i).isDirectory() &&-        !excludeFolder.includes(i)-      )-    })-    .map(i => {-      const p = path.join(__dirname, i)-      const tests = fs-        .readdirSync(p)-        .filter(j => fs.statSync(path.join(p, j)).isDirectory())-        .map(j => path.join(p, j))-      return tests-    })+const fs = require("fs");+const path = require("path");+const { execSync } = require("child_process");+const chalk = require("chalk");+const semver = require("semver");++const examplesFolder = path.join(__dirname, "src");++function getAllExamples(pathToCheck) {+  const directoriesToTest = [];+  for (const fd of fs.readdirSync(pathToCheck)) {+    const absPath = path.join(pathToCheck, fd);+    if (fs.existsSync(path.join(absPath, "package.json"))) {+      directoriesToTest.push(absPath);+      continue;+    }+    if (fs.statSync(absPath).isDirectory()) {+      directoriesToTest.push(...getAllExamples(absPath));+    }+  }+  return directoriesToTest; } -getAllTests().map(tests => {-  tests.map(i => {-    console.log(chalk.green(`testing: ${i}`))-    const p = require(path.join(i, 'package.json'))-    if (p.engines && p.engines.node) {-      const currentNodeVersion = process.versions.node-      const range = p.engines.node-      const engineOk = semver.satisfies(currentNodeVersion, range)-      if (!engineOk) {-        console.warn(-          chalk.yellow(`${i} require Node.js ${range}, current is ${currentNodeVersion}, skipping`)+const passed = [];+const failedInstalls = [];+const noTest = [];+const failedTests = [];+for (directoryToTest of getAllExamples(examplesFolder)) {+  console.log(chalk.green(`testing: ${directoryToTest}`));+  const pkgJson = require(path.join(directoryToTest, "package.json"));+  if (pkgJson.engines && pkgJson.engines.node) {+    const currentNodeVersion = process.versions.node;+    const range = pkgJson.engines.node;+    const engineOk = semver.satisfies(currentNodeVersion, range);+    if (!engineOk) {+      console.warn(+        chalk.yellow(+          `${directoryToTest} require Node.js ${range}, current is ${currentNodeVersion}, skipping`         )-        return-      }+      );+      continue;     }-    const stdout = execSync('npm install', {-      cwd: i-    })-    console.log(stdout.toString())-  })-})+  }++  try {+    const stdout = execSync("npm install", { cwd: directoryToTest });+    console.log(stdout.toString());+  } catch (err) {+    console.log(err);+    failedInstalls.push(directoryToTest);+    continue;+  }++  let testCommand;+  if ("scripts" in pkgJson && "start" in pkgJson.scripts) {+    testCommand = "npm start";+  } else if ("scripts" in pkgJson && "test" in pkgJson.scripts) {+    testCommand = "npm test";+  } else if ("main" in pkgJson) {+    testCommand = `node ${pkgJson.main}`+  } else {+    noTest.push(directoryToTest);+    continue;+  }++  try {+    const stdout = execSync(testCommand, { cwd: directoryToTest });+    console.log(stdout.toString());+    passed.push(directoryToTest);+  } catch (err) {+    console.log(err);+    failedTests.push(directoryToTest);+  }+}++passed.map((dir) => console.log(chalk.green(`passed: ${dir}`)));++if (noTest.length > 0) {+  console.warn(chalk.yellow("no test found:"));+  noTest.map((dir) => console.warn(chalk.yellow(`    ${dir}`)));+}++if (failedInstalls.length > 0) {+  console.error(chalk.red("failed to install:"));+  failedInstalls.map((dir) => console.warn(chalk.red(`    ${dir}`)));+}+if (failedTests.length > 0) {+  console.error(chalk.red("failed tests:"));+  failedTests.map((dir) => console.warn(chalk.red(`    ${dir}`)));+}

thread_safe_function_counting/node-addon-api/addon.cc

deleted file mode 100644@@ -1,106 +0,0 @@-#include <chrono>-#include <thread>-#include "napi.h"--constexpr size_t ARRAY_LENGTH = 10;--// Data structure representing our thread-safe function context.-struct TsfnContext {-  TsfnContext(Napi::Env env) : deferred(Napi::Promise::Deferred::New(env)) {-    for (size_t i = 0; i < ARRAY_LENGTH; ++i) ints[i] = i;-  };--  // Native Promise returned to JavaScript-  Napi::Promise::Deferred deferred;--  // Native thread-  std::thread nativeThread;--  // Some data to pass around-  int ints[ARRAY_LENGTH];--  Napi::ThreadSafeFunction tsfn;-};--// The thread entry point. This takes as its arguments the specific-// threadsafe-function context created inside the main thread.-void threadEntry(TsfnContext* context);--// The thread-safe function finalizer callback. This callback executes-// at destruction of thread-safe function, taking as arguments the finalizer-// data and threadsafe-function context.-void FinalizerCallback(Napi::Env env, void* finalizeData, TsfnContext* context);--// Exported JavaScript function. Creates the thread-safe function and native-// thread. Promise is resolved in the thread-safe function's finalizer.-Napi::Value CreateTSFN(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();--  // Construct context data-  auto testData = new TsfnContext(env);--  // Create a new ThreadSafeFunction.-  testData->tsfn = Napi::ThreadSafeFunction::New(-      env,                           // Environment-      info[0].As<Napi::Function>(),  // JS function from caller-      "TSFN",                        // Resource name-      0,                             // Max queue size (0 = unlimited).-      1,                             // Initial thread count-      testData,                      // Context,-      FinalizerCallback,             // Finalizer-      (void*)nullptr                 // Finalizer data-  );-  testData->nativeThread = std::thread(threadEntry, testData);--  // Return the deferred's Promise. This Promise is resolved in the thread-safe-  // function's finalizer callback.-  return testData->deferred.Promise();-}--// The thread entry point. This takes as its arguments the specific-// threadsafe-function context created inside the main thread.-void threadEntry(TsfnContext* context) {-  // This callback transforms the native addon data (int *data) to JavaScript-  // values. It also receives the treadsafe-function's registered callback, and-  // may choose to call it.-  auto callback = [](Napi::Env env, Napi::Function jsCallback, int* data) {-    jsCallback.Call({Napi::Number::New(env, *data)});-  };--  for (size_t index = 0; index < ARRAY_LENGTH; ++index) {-    // Perform a call into JavaScript.-    napi_status status =-        context->tsfn.BlockingCall(&context->ints[index], callback);--    if (status != napi_ok) {-      Napi::Error::Fatal(-          "ThreadEntry",-          "Napi::ThreadSafeNapi::Function.BlockingCall() failed");-    }-    // Sleep for some time.-    std::this_thread::sleep_for(std::chrono::milliseconds(200));-  }--  // Release the thread-safe function. This decrements the internal thread-  // count, and will perform finalization since the count will reach 0.-  context->tsfn.Release();-}--void FinalizerCallback(Napi::Env env,-                       void* finalizeData,-                       TsfnContext* context) {-  // Join the thread-  context->nativeThread.join();--  // Resolve the Promise previously returned to JS via the CreateTSFN method.-  context->deferred.Resolve(Napi::Boolean::New(env, true));-  delete context;-}--// Addon entry point-Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports["createTSFN"] = Napi::Function::New(env, CreateTSFN);-  return exports;-}--NODE_API_MODULE(addon, Init)

thread_safe_function_counting/node-addon-api/addon.js

deleted file mode 100644@@ -1,9 +0,0 @@-const { createTSFN } = require('bindings')('addon');--const callback = (...args) => { -    console.log(new Date, ...args); -};--void async function() {-    console.log(await createTSFN(callback));-}();

thread_safe_function_counting/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,21 +0,0 @@-{-  'targets': [{-    'target_name': 'addon',-    'defines': ['V8_DEPRECATION_WARNINGS=1'],-    'sources': ['addon.cc'],-    'include_dirs': ["<!@(node -p \"require('node-addon-api').include\")"],-    'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],-    'cflags!': ['-fno-exceptions'],-    'cflags_cc!': ['-fno-exceptions'],-    'xcode_settings': {-      'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',-      'CLANG_CXX_LIBRARY': 'libc++',-      'MACOSX_DEPLOYMENT_TARGET': '10.7',-    },-    'msvs_settings': {-      'VCCLCompilerTool': {-        'ExceptionHandling': 1-      },-    },-  }]-}

thread_safe_function_counting/node-addon-api/package.json

deleted file mode 100644@@ -1,15 +0,0 @@-{-  "name": "tsfn-counting",-  "version": "0.0.0",-  "description": "Thread-safe Function Example",-  "main": "addon.js",-  "private": true,-  "gypfile": true,-  "dependencies": {-    "node-addon-api": "*",-    "bindings": "*"-  },-  "engines": {-    "node": ">= 10.16.0"-  }-}

thread_safe_function_round_trip/napi/binding.gyp

deleted file mode 100644@@ -1,8 +0,0 @@-{-  'targets': [-    {-      'target_name': 'round_trip',-      'sources': [ 'round_trip.c' ]-    }-  ]-}

thread_safe_function_round_trip/napi/index.js

deleted file mode 100644@@ -1,14 +0,0 @@-const bindings = require('bindings')('round_trip');--bindings.startThread(item => {-  const thePrime = item.prime;-  console.log('The prime: ' + thePrime);--  // Answer the call with a 90% probability of returning true somewhere between-  // 200 and 400 ms from now.-  setTimeout(() => {-    const theAnswer = (Math.random() > 0.1);-    console.log(thePrime + ': answering with ' + theAnswer);-    bindings.registerReturnValue(item, theAnswer);-  }, Math.random() * 200 + 200);-});

thread_safe_function_round_trip/napi/package.json

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "name": "thread_safe_function_round_trip",-  "version": "0.0.0",-  "description": "Thread-safe Function Example With JavaScript Round Trip",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1"-  },-  "engines": {-    "node": ">= 10.6.0"-  },-  "scripts": {-    "test": "node index.js"-  },-  "gypfile": true-}

thread_safe_function_round_trip/napi/round_trip.c

deleted file mode 100644@@ -1,427 +0,0 @@-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <uv.h>-#define NAPI_EXPERIMENTAL-#include <node_api.h>--#define CHECK(expr) \-  { \-    if ((expr) == 0) { \-      fprintf(stderr, "%s:%d: failed assertion `%s'\n", __FILE__, __LINE__, #expr); \-      fflush(stderr); \-      abort(); \-    } \-  }--#define REPORT_EVERY 1000--// An item that will be generated from the thread, passed into JavaScript, and-// ultimately marked as resolved when the JavaScript passes it back into the-// addon instance with a return value.-typedef struct ThreadItem {-  // This field is read-only once set, so it need not be protected by the mutex.-  int the_prime;--  // This field is only accessed from the secondary thread, so it also need not-  // be protected by the mutex.-  struct ThreadItem* next;--  // These two values must be protected by the mutex.-  bool call_has_returned;-  bool return_value;-} ThreadItem;--// The data associated with an instance of the addon. This takes the place of-// global static variables, while allowing multiple instances of the addon to-// co-exist.-typedef struct {-  uv_mutex_t check_status_mutex;-  uv_thread_t the_thread;-  napi_threadsafe_function tsfn;-  napi_ref thread_item_constructor;-  bool js_accepts;-} AddonData;--// This function is responsible for converting the native data coming in from-// the secondary thread to JavaScript values, and for calling the JavaScript-// function. It may also be called with `env` and `js_cb` set to `NULL` when-// Node.js is terminating and there are items coming in from the secondary-// thread left to process. In that case, this function does nothing, since it is-// the secondary thread that frees the items.-static void CallJs(napi_env env, napi_value js_cb, void* context, void* data) {-  AddonData* addon_data = (AddonData*)context;-  napi_value constructor;--  // The semantics of this example are such that, once the JavaScript returns-  // `false`, the `ThreadItem` structures can no longer be accessed, because the-  // thread terminates and frees them all. Thus, we record the instant when-  // JavaScript returns `false` by setting `addon_data->js_accepts` to `false`-  // in `RegisterReturnValue` below, and we use the value here to decide whether-  // the data coming in from the secondary thread is stale or not.-  if (addon_data->js_accepts && !(env == NULL || js_cb == NULL)) {-    napi_value undefined, js_thread_item;-    // Retrieve the JavaScript `undefined` value. This will serve as the `this`-    // value for the function call.-    CHECK(napi_get_undefined(env, &undefined) == napi_ok);--    // Retrieve the constructor for the JavaScript class from which the item-    // holding the native data will be constructed.-    CHECK(napi_get_reference_value(env,-                                    addon_data->thread_item_constructor,-                                    &constructor) == napi_ok);--    // Construct a new instance of the JavaScript class to hold the native item.-    CHECK(napi_new_instance(env,-                             constructor,-                             0,-                             NULL,-                             &js_thread_item) == napi_ok);--    // Associate the native item with the newly constructed JavaScript object.-    // We assume that the JavaScript side will eventually pass this JavaScript-    // object back to us via `RegisterReturnValue`, which will allow the-    // eventual deallocation of the native data. That's why we do not provide a-    // finalizer here.-    CHECK(napi_wrap(env, js_thread_item, data, NULL, NULL, NULL) == napi_ok);--    // Call the JavaScript function with the item as wrapped into an instance of-    // the JavaScript `ThreadItem` class and the prime.-    CHECK(napi_call_function(env,-                              undefined,-                              js_cb,-                              1,-                              &js_thread_item,-                              NULL) == napi_ok);-  }-}--// When the thread is finished we join it to prevent memory leaks. We can safely-// set `addon_data->tsfn` to NULL, because the thread-safe function will be-// cleaned up in the background in response to the secondary thread having-// called `napi_release_threadsafe_function()`.-static void ThreadFinished(napi_env env, void* data, void* context) {-  (void) context;-  AddonData* addon_data = (AddonData*)data;-  CHECK(uv_thread_join(&(addon_data->the_thread)) == 0);-  addon_data->tsfn = NULL;-}--// The secondary thread produces prime numbers using a very inefficient-// algorithm and calls into JavaScript with every REPORT_EVERYth prime number.-// After each call it checks whether any of the previous calls have produced a-// return value, and, if so, whether that return value is `false`. A `false`-// return value indicates that the JavaScript side is no longer interested in-// receiving any values and that the thread and the thread-safe function are to-// be cleaned up. On the JavaScript thread, this is marked in-// `addon_data->js_accepts`. When set to `false`, the JavaScript thread will not-// access the thread items any further, so they can be safely deleted on this-// thread.-static void PrimeThread(void* data) {-  AddonData* addon_data = (AddonData*) data;-  int idx_outer, idx_inner;-  int prime_count = 0;-  ThreadItem* first = NULL;-  ThreadItem* current = NULL;-  ThreadItem* previous = NULL;-  ThreadItem* returned = NULL;--  // Check each integer whether it's a prime.-  for (idx_outer = 2 ;; idx_outer++) {--    // Check whether `idx_outer` is divisible by anything up to and not-    // including itself.-    for (idx_inner = 2;-        idx_inner < idx_outer && idx_outer % idx_inner != 0;-        idx_inner++);--    // If we find a prime, and it is REPORT_EVERY primes away from the previous-    // prime we found, then we send it to JavaScript.-    if (idx_inner >= idx_outer && (++prime_count % REPORT_EVERY) == 0) {-      // Create a new thread item and attach it to the list of outstanding-      // `ThreadItem` structures representing calls into JavaScript for which-      // no return value has yet been established.-      current = memset(malloc(sizeof(*current)), 0, sizeof(*current));-      current->the_prime = idx_outer;-      current->call_has_returned = false;-      current->return_value = false;-      current->next = first;-      first = current;--      // Pass the new item into JavaScript.-      CHECK(napi_call_threadsafe_function(addon_data->tsfn,-                                           first,-                                           napi_tsfn_blocking) == napi_ok);-    }--    // Pass over all outstanding thread items and check whether any of them have-    // returned.-    for (current = first, previous = NULL, returned = NULL;-        current != NULL && returned == NULL;-        previous = current,-        current = current->next) {-      uv_mutex_lock(&(addon_data->check_status_mutex));-      if (current->call_has_returned) {-        // Unhook the call that has returned from the list.-        if (previous != NULL) {-          previous->next = current->next;-        } else {-          first = current->next;-        }-        returned = current;-      }-      uv_mutex_unlock(&(addon_data->check_status_mutex));-    }--    // Process a return value. Free the `ThreadItem` that returned it, and break-    // out of the loop if the return value was `false`.-    if (returned != NULL) {-      // Save the return value to a local variable because we have to check it-      // after having freed the structure wherein it is stored.-      bool return_value = returned->return_value;-      free(returned);-      if (!return_value) {-        break;-      }-    }-  }--  // Before terminating the thread we free the remaining queue items. `CallJs`-  // will be called with pointers to these items, perhaps after this thread has-  // already freed them, but that's OK, because on the JavaScript thread-  // `addon_data->js_accepts` will certainly have been set to `false`, and so-  // `CallJs` will not dereference the stale pointers.-  for (current = first; current != NULL;) {-    previous = current;-    current = current->next;-    free(previous);-  }--  // Release the thread-safe function. This causes it to be cleaned up in the-  // background.-  CHECK(napi_release_threadsafe_function(addon_data->tsfn,-                                          napi_tsfn_release) == napi_ok);-}--// This binding can be called from JavaScript to start the asynchronous prime-// generator.-static napi_value StartThread(napi_env env, napi_callback_info info) {-  size_t argc = 1;-  napi_value js_cb, work_name;-  AddonData* addon_data;--  // The binding accepts one parameter - the JavaScript callback function to-  // call.-  CHECK(napi_get_cb_info(env,-                          info,-                          &argc,-                          &js_cb,-                          NULL,-                          (void*)&addon_data) == napi_ok);--  // We do not create a second thread if one is already running.-  CHECK(addon_data->tsfn == NULL && "Work already in progress");--  addon_data->js_accepts = true;--  // This string describes the asynchronous work.-  CHECK(napi_create_string_utf8(env,-                                 "Thread-safe Function Round Trip Example",-                                 NAPI_AUTO_LENGTH,-                                 &work_name) == napi_ok);--  // The thread-safe function will be created with an unlimited queue and with-  // an initial thread count of 1. The secondary thread will release the-  // thread-safe function, decreasing its thread count to 0, thereby setting off-  // the process of cleaning up the thread-safe function.-  CHECK(napi_create_threadsafe_function(env,-                                         js_cb,-                                         NULL,-                                         work_name,-                                         0,-                                         1,-                                         addon_data,-                                         ThreadFinished,-                                         addon_data,-                                         CallJs,-                                         &addon_data->tsfn) == napi_ok);--  // Create the thread that will produce primes and that will call into-  // JavaScript using the thread-safe function.-  CHECK(uv_thread_create(&(addon_data->the_thread), PrimeThread, addon_data) == 0);--  return NULL;-}--static bool-is_thread_item (napi_env env, napi_ref constructor_ref, napi_value value) {-  bool validate;-  napi_value constructor;-  CHECK(napi_get_reference_value(env,-                                  constructor_ref,-                                  &constructor) == napi_ok);-  CHECK(napi_instanceof(env, value, constructor, &validate) == napi_ok);-  return validate;-}--// We use a separate binding to register a return value for a given call into-// JavaScript, represented by a `ThreadItem` object on both the JavaScript side-// and the native side. This allows the JavaScript side to asynchronously-// determine the return value.-static napi_value RegisterReturnValue(napi_env env, napi_callback_info info) {-  // This function accepts two parameters:-  // 1. The thread item passed into JavaScript via `CallJs`, and-  // 2. The desired return value.-  size_t argc = 2;-  napi_value argv[2];-  AddonData* addon_data;-  bool return_value;-  ThreadItem* item;--  // Retrieve the parameters with which this function was called.-  CHECK(napi_get_cb_info(env,-                          info,-                          &argc,-                          argv,-                          NULL,-                          (void*)&addon_data) == napi_ok);--  // If this function recorded a return value of `false` before, it means that-  // the thread and the associated thread-safe function are shutting down. This,-  // in turn means that the wrapped `ThreadItem` that was received in the first-  // argument may also be stale. Our best strategy is to do nothing and return-  // to JavaScript.-  if (!addon_data->js_accepts) {-    return NULL;-  }--  CHECK(argc == 2 && "Exactly two arguments were received");--  // Make sure the first parameter is an instance of the `ThreadItem` class.-  // This type check ensures that there *is* a pointer stored inside the-  // JavaScript object, and that the pointer is to a `ThreadItem` structure.-  CHECK(is_thread_item(env, addon_data->thread_item_constructor, argv[0]));--  // Retrieve the native data from the item.-  CHECK(napi_unwrap(env, argv[0], (void**)&item) == napi_ok);--  // Retrieve the desired return value.-  CHECK(napi_get_value_bool(env, argv[1], &return_value) == napi_ok);--  // Set `js_accepts` to false in case the JavaScript callback returned false.-  if (addon_data->js_accepts) {-    addon_data->js_accepts = return_value;-  }--  // Mark the thread item as resolved, and record the JavaScript return value.-  uv_mutex_lock(&(addon_data->check_status_mutex));-  item->call_has_returned = true;-  item->return_value = return_value;-  uv_mutex_unlock(&(addon_data->check_status_mutex));--  return NULL;-}--// Constructor for instances of the `ThreadItem` class. This doesn't need to do-// anything since all we want the class for is to be able to type-check-// JavaScript objects that carry within them a pointer to a native `ThreadItem`-// structure.-static napi_value ThreadItemConstructor(napi_env env, napi_callback_info info) {-  return NULL;-}--// Getter for the `prime` property of the `ThreadItem` class.-static napi_value GetPrime(napi_env env, napi_callback_info info) {-  napi_value jsthis, prime_property;-  AddonData* ad;-  CHECK(napi_ok == napi_get_cb_info(env, info, 0, 0, &jsthis, (void*)&ad));-  CHECK(is_thread_item(env, ad->thread_item_constructor, jsthis));-  ThreadItem* item;-  CHECK(napi_ok == napi_unwrap(env, jsthis, (void**)&item));-  CHECK(napi_ok == napi_create_int32(env, item->the_prime, &prime_property));-  return prime_property;-}--static void addon_is_unloading(napi_env env, void* data, void* hint) {-  AddonData* addon_data = (AddonData*)data;-  uv_mutex_destroy(&(addon_data->check_status_mutex));-  CHECK(napi_delete_reference(env,-                               addon_data->thread_item_constructor) == napi_ok);-  free(data);-}--// Initialize an instance of this addon. This function may be called multiple-// times if multiple instances of Node.js are running on multiple threads, or if-// there are multiple Node.js contexts running on the same thread. The return-// value and the formal parameters in comments remind us that the function body-// that follows, within which we initialize the addon, has available to it the-// variables named in the formal parameters, and that it must return a-// `napi_value`.-/*napi_value*/ NAPI_MODULE_INIT(/*napi_env env, napi_value exports*/) {-  // Create the native data that will be associated with this instance of the-  // addon.-  AddonData* addon_data =-      memset(malloc(sizeof(*addon_data)), 0, sizeof(*addon_data));--  // Attach the addon data to the exports object to ensure that they are-  // destroyed together.-  CHECK(napi_wrap(env,-                   exports,-                   addon_data,-                   addon_is_unloading,-                   NULL,-                   NULL) == napi_ok);--  // Initialize the various members of the `AddonData` associated with this-  // addon instance.-  CHECK(uv_mutex_init(&(addon_data->check_status_mutex)) == 0);--  napi_value thread_item_class;-  napi_property_descriptor thread_item_properties[] = {-    { "prime", 0, 0, GetPrime, 0, 0, napi_enumerable, addon_data }-  };-  CHECK(napi_define_class(env,-                           "ThreadItem",-                           NAPI_AUTO_LENGTH,-                           ThreadItemConstructor,-                           addon_data,-                           1,-                           thread_item_properties,-                           &thread_item_class) == napi_ok);-  CHECK(napi_create_reference(env,-                               thread_item_class,-                               1,-                               &(addon_data->thread_item_constructor)) ==-                                  napi_ok);--  // Expose the two bindings this addon provides.-  napi_property_descriptor export_properties[] = {-    {-      "startThread",-      NULL,-      StartThread,-      NULL,-      NULL,-      NULL,-      napi_default,-      addon_data-    },-    {-      "registerReturnValue",-      NULL,-      RegisterReturnValue,-      NULL,-      NULL,-      NULL,-      napi_default,-      addon_data-    }-  };-  CHECK(napi_define_properties(env,-                                exports,-                                sizeof(export_properties) /-                                    sizeof(export_properties[0]),-                                export_properties) == napi_ok);--  return exports;-}

thread_safe_function_with_object_wrap/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "targets": [-    {-      "target_name": "tsfn_object_wrap",-      "sources": [-        "tsfn_object_wrap.cc",-      ],-      "defines": [-        "NAPI_DISABLE_CPP_EXCEPTIONS",-        "NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS"-      ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-    }-  ]-}

thread_safe_function_with_object_wrap/node-addon-api/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "tsfn-test",-  "version": "1.0.0",-  "description": "",-  "main": "index.js",-  "scripts": {-    "test": "echo \"Error: no test specified\" && exit 1"-  },-  "author": "",-  "dependencies": {-    "bindings": "*",-    "node-addon-api": "^7.0.0"-  }-}

thread_safe_function_with_object_wrap/node-addon-api/tsfn_object_wrap.cc

deleted file mode 100644@@ -1,77 +0,0 @@-#include <inttypes.h>-#include <napi.h>-#include <thread>--// A secondary thread increments a value starting from 0 and calls a JS callback-// on the JavaScript main thread.--// The ObjectWrap subclass whose instances own such a secondary thread.-class TsfnObjectWrap : public Napi::ObjectWrap<TsfnObjectWrap> {- public:-  static Napi::Object Init(Napi::Env env) {-    return DefineClass(env, "TsfnObjectWrap", {});-  }--  TsfnObjectWrap(const Napi::CallbackInfo& info)-      : Napi::ObjectWrap<TsfnObjectWrap>(info) {-    // Whenever we construct a new instance of type TsfnObjectWrap, we construct-    // a thread-safe function that can be called from a secondary thread and-    // which provides a value to the JavaScript main thread.-    _tsfn = Napi::ThreadSafeFunction::New(-        info.Env(), info[0].As<Napi::Function>(), "TsfnObjectWrap", 1, 2);--    _thread = std::thread(&TsfnObjectWrap::Thread, std::ref(_tsfn));-  }--  ~TsfnObjectWrap() {-    _tsfn.Abort();-    _thread.join();-  }-- private:-  // This is the secondary thread.-  static void Thread(const Napi::ThreadSafeFunction& tsfn) {-    int64_t the_value = 0;-    int64_t buffer[3] = {0, 0, 0};-    int idx = 0;--    // Since we're calling the JavaScript main thread in a blocking fashion,-    // a buffer of three values is sufficient for synchronizing with the main-    // thread without losing a single value and without having to allocate an-    // integer on the heap for each call into JavaScript.-    while (true) {-      buffer[idx] = the_value;-      idx = (idx + 1) % 3;-      int64_t* value_ref = &buffer[idx];-      napi_status status = tsfn.BlockingCall(-          value_ref, [](Napi::Env env, Napi::Function fn, int64_t* data) {-            int64_t native_value = *data;-            Napi::Value result =-                fn.Call({Napi::Number::New(env, native_value)});-            if (result.IsEmpty()) {-              printf("main with %" PRId64 ": result was empty!\n",-                     native_value);-            } else {-              printf("main with %" PRId64 ": Done!\n",-                     result.As<Napi::Number>().Int64Value());-            }-          });-      // We break out of the infinite loop when we're informed that the thread--      // safe function is being torn down.-      if (status == napi_closing) {-        break;-      }-      the_value++;-    }-  }--  Napi::ThreadSafeFunction _tsfn;-  std::thread _thread;-};--// Boilerplate code to define an add-on that consists of the above class.-Napi::Object TsfnObjectWrapExampleInit(Napi::Env env, Napi::Object exports) {-  return TsfnObjectWrap::Init(env);-}--NODE_API_MODULE(TsfnObjectWrapExample, TsfnObjectWrapExampleInit)

thread_safe_function_with_object_wrap/node-addon-api/tsfn_object_wrap.js

deleted file mode 100644@@ -1,18 +0,0 @@-const TsfnObjectWrap = require('bindings')('tsfn_object_wrap.node')-const x = new TsfnObjectWrap((value) => {-  // Do something, anything, with x to keep it in scope, otherwise the instance-  // will be collected and the process will exit.-  x.someProperty = value;--  console.log('JS1: Called with ' + value);-  return -value;-});--const y = new TsfnObjectWrap((value) => {-  // Do something, anything, with y to keep it in scope, otherwise the instance-  // will be collected and the process will exit.-  y.someProperty = value;--  console.log('JS2: Called with ' + value);-  return -value;-});

threadsafe-async-iterator/node-addon-api/CMakeLists.txt

deleted file mode 100644@@ -1,23 +0,0 @@-project (example)-include_directories(${CMAKE_JS_INC} node_modules/node-addon-api/)-cmake_minimum_required(VERSION 3.18)--set(CMAKE_CXX_STANDARD 20)-set(CMAKE_CXX_STANDARD_REQUIRED ON)-include_directories(${CMAKE_JS_INC})-file(GLOB SOURCE_FILES "*.cc")-add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")-target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})--# Include Node-API wrappers-execute_process(COMMAND node -p "require('node-addon-api').include"-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}-        OUTPUT_VARIABLE NODE_ADDON_API_DIR-        )-string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})--target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})--# define NAPI_VERSION-add_definitions(-DNAPI_VERSION=6)

threadsafe-async-iterator/node-addon-api/example.cc

deleted file mode 100644@@ -1,163 +0,0 @@-#include <napi.h>-#include <condition_variable>-#include <functional>-#include <memory>-#include <mutex>-#include <optional>-#include <thread>--using namespace Napi;--class ThreadSafeAsyncIteratorExample-    : public ObjectWrap<ThreadSafeAsyncIteratorExample> {- public:-  ThreadSafeAsyncIteratorExample(const CallbackInfo& info)-      : ObjectWrap<ThreadSafeAsyncIteratorExample>(info),-        _current(info[0].As<Number>()),-        _last(info[1].As<Number>()) {}--  static Object Init(Napi::Env env, Napi::Object exports);--  Napi::Value Iterator(const CallbackInfo& info);-- private:-  using Context = ThreadSafeAsyncIteratorExample;--  struct DataType {-    std::unique_ptr<Promise::Deferred> deferred;-    bool done;-    std::optional<int> value;-  };--  static void CallJs(Napi::Env env,-                     Function callback,-                     Context* context,-                     DataType* data);--  using TSFN = TypedThreadSafeFunction<Context, DataType, CallJs>;--  using FinalizerDataType = void;--  int _current;-  int _last;-  TSFN _tsfn;-  std::thread _thread;-  std::unique_ptr<Promise::Deferred> _deferred;--  // Thread-safety-  std::mutex _mtx;-  std::condition_variable _cv;--  void threadEntry();--  static void FinalizerCallback(Napi::Env env,-                                void*,-                                ThreadSafeAsyncIteratorExample* context);-};--Object ThreadSafeAsyncIteratorExample::Init(Napi::Env env,-                                            Napi::Object exports) {-  Napi::Function func =-      DefineClass(env,-                  "ThreadSafeAsyncIteratorExample",-                  {InstanceMethod(Napi::Symbol::WellKnown(env, "asyncIterator"),-                                  &ThreadSafeAsyncIteratorExample::Iterator)});--  exports.Set("ThreadSafeAsyncIteratorExample", func);-  return exports;-}--Napi::Value ThreadSafeAsyncIteratorExample::Iterator(const CallbackInfo& info) {-  auto env = info.Env();--  if (_thread.joinable()) {-    Napi::Error::New(env, "Concurrent iterations not implemented.")-        .ThrowAsJavaScriptException();-    return Napi::Value();-  }--  _tsfn =-      TSFN::New(info.Env(),-                "tsfn",-                0,-                1,-                this,-                std::function<decltype(FinalizerCallback)>(FinalizerCallback));--  // To prevent premature garbage collection; Unref in TFSN finalizer-  Ref();--  // Create thread-  _thread = std::thread(&ThreadSafeAsyncIteratorExample::threadEntry, this);--  // Create iterable-  auto iterable = Napi::Object::New(env);--  iterable["next"] =-      Function::New(env, [this](const CallbackInfo& info) -> Napi::Value {-        std::lock_guard<std::mutex> lk(_mtx);-        auto env = info.Env();-        if (_deferred) {-          Napi::Error::New(env, "Concurrent iterations not implemented.")-              .ThrowAsJavaScriptException();-          return Napi::Value();-        }-        _deferred = std::make_unique<Promise::Deferred>(env);-        _cv.notify_all();-        return _deferred->Promise();-      });--  return iterable;-}--void ThreadSafeAsyncIteratorExample::threadEntry() {-  while (true) {-    std::unique_lock<std::mutex> lk(_mtx);-    _cv.wait(lk, [this] { return this->_deferred != nullptr; });-    auto done = _current > _last;-    if (done) {-      _tsfn.BlockingCall(new DataType{std::move(this->_deferred), true, {}});-      break;-    } else {-      std::this_thread::sleep_for(-          std::chrono::seconds(1));  // Simulate CPU-intensive work-      _tsfn.BlockingCall(-          new DataType{std::move(this->_deferred), false, _current++});-    }-  }-  _tsfn.Release();-}--void ThreadSafeAsyncIteratorExample::CallJs(Napi::Env env,-                                            Function callback,-                                            Context* context,-                                            DataType* data) {-  if (env != nullptr) {-    auto value = Object::New(env);--    if (data->done) {-      value["done"] = Boolean::New(env, true);-    } else {-      value["done"] = Boolean::New(env, false);-      value["value"] = Number::New(env, data->value.value());-    }-    data->deferred->Resolve(value);-  }--  if (data != nullptr) {-    delete data;-  }-}--void ThreadSafeAsyncIteratorExample::FinalizerCallback(-    Napi::Env env, void*, ThreadSafeAsyncIteratorExample* context) {-  context->_thread.join();-  context->Unref();-}--Napi::Object Init(Napi::Env env, Object exports) {-  ThreadSafeAsyncIteratorExample::Init(env, exports);-  return exports;-}--NODE_API_MODULE(example, Init)

threadsafe-async-iterator/node-addon-api/index.js

deleted file mode 100644@@ -1,14 +0,0 @@-const { ThreadSafeAsyncIteratorExample } = require('bindings')('example');--async function main(from, to) {-    const iterator = new ThreadSafeAsyncIteratorExample(from, to);-    for await (const value of iterator) {-        console.log(value);-    }-}--main(0, 5)-    .catch(e => {-        console.error(e);-        process.exit(1);-    });

threadsafe-async-iterator/node-addon-api/package.json

deleted file mode 100644@@ -1,16 +0,0 @@-{-  "name": "threadsafe-async-iterator-example",-  "version": "0.0.0",-  "description": "Async iterator example with threadsafe functions using node-addon-api",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "^1.5.0",-    "cmake-js": "^6.3.0",-    "node-addon-api": "^5.0.0"-  },-  "scripts": {-    "test": "node index.js",-    "install": "cmake-js compile"-  }-}

typed_array_to_native/node-addon-api/binding.gyp

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "targets": [-    {-      "target_name": "typed_array_to_native",-      "cflags!": [ "-fno-exceptions" ],-      "cflags_cc!": [ "-fno-exceptions" ],-      "sources": [ "typed_array_to_native.cc" ],-      "include_dirs": [-        "<!@(node -p \"require('node-addon-api').include\")"-      ],-      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],-    }-  ]-}

typed_array_to_native/node-addon-api/index.js

deleted file mode 100644@@ -1,15 +0,0 @@-const binding = require('bindings')('typed_array_to_native');--{-    const byteArray = Uint8Array.from([10, 20, 30, 50, 25, 17]);-    console.log("byteArray: ", byteArray);-    binding.AcceptByteArray(byteArray);-}-console.log("---------");--{-    const array = [7, 15, 26, 58, 64];-    console.log("array: ", array);-    const byteArray = binding.CreateByteArray(array);-    console.log("byteArray: ", byteArray);-}\ No newline at end of file

typed_array_to_native/node-addon-api/package.json

deleted file mode 100644@@ -1,14 +0,0 @@-{-  "name": "typed_array_to_native",-  "version": "0.0.0",-  "description": "Shows how to read and create typed arrays",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "node-addon-api": "^1.0.0"-  },-  "scripts": {-    "test": "node index.js"-  }-}

typed_array_to_native/node-addon-api/typed_array_to_native.cc

deleted file mode 100644@@ -1,108 +0,0 @@-#include <napi.h>-#include <cstdio>--static Napi::Value AcceptByteArray(const Napi::CallbackInfo& info) {-  if (info.Length() != 1) {-    Napi::Error::New(info.Env(), "Expected exactly one argument")-        .ThrowAsJavaScriptException();-    return info.Env().Undefined();-  }--  if (!info[0].IsTypedArray()) {-    Napi::Error::New(info.Env(), "Expected a TypedArray")-        .ThrowAsJavaScriptException();-    return info.Env().Undefined();-  }-  Napi::TypedArray typedArray = info[0].As<Napi::TypedArray>();--  if (typedArray.TypedArrayType() != napi_uint8_array) {-    Napi::Error::New(info.Env(), "Expected an Uint8Array")-        .ThrowAsJavaScriptException();-    return info.Env().Undefined();-  }-  Napi::Uint8Array uint8Array = typedArray.As<Napi::Uint8Array>();--  // Copy to std::vector<uint8_t>:-  std::vector<uint8_t> bytes(uint8Array.Data(),-                             uint8Array.Data() + uint8Array.ElementLength());-  printf("std::vector<uint8_t> from Uint8Array: [");-  for (uint8_t byte : bytes) {-    printf("%d, ", byte);-  }-  printf("\b\b]\n");--  return info.Env().Undefined();-}--static Napi::Value CreateByteArray(const Napi::CallbackInfo& info) {-  if (info.Length() != 1) {-    Napi::Error::New(info.Env(), "Expected exactly one argument")-        .ThrowAsJavaScriptException();-    return info.Env().Undefined();-  }--  if (!info[0].IsArray()) {-    Napi::Error::New(info.Env(), "Expected an Array")-        .ThrowAsJavaScriptException();-    return info.Env().Undefined();-  }-  Napi::Array array = info[0].As<Napi::Array>();-  size_t arrayLength = array.Length();--  // Create std::vector<uint8_t> out of array.-  // We allocate it on the heap to allow wrapping it up into ArrayBuffer.-  std::unique_ptr<std::vector<uint8_t>> nativeArray =-      std::make_unique<std::vector<uint8_t>>(arrayLength, 0);-  for (size_t i = 0; i < arrayLength; ++i) {-    Napi::Value arrayItem = array[i];-    if (!arrayItem.IsNumber()) {-      Napi::Error::New(info.Env(), "Expected a Number as Array Item")-          .ThrowAsJavaScriptException();-      return info.Env().Undefined();-    }-    Napi::Number number = arrayItem.As<Napi::Number>();-    double numberValue = number.DoubleValue();-    if (numberValue < 0 || numberValue > 255) {-      Napi::Error::New(info.Env(),-                       "Array Item Number value is out of range [0..255]")-          .ThrowAsJavaScriptException();-      return info.Env().Undefined();-    }--    (*nativeArray)[i] = static_cast<uint8_t>(numberValue);-  }--  printf("std::vector<uint8_t> from Array: [");-  for (uint8_t byte : *nativeArray) {-    printf("%d, ", byte);-  }-  printf("\b\b]\n");--  // Wrap up the std::vector into the ArrayBuffer.-  // Note: instead of wrapping the std::vector we could allow ArrayBuffer to-  // create internal storage that copies the std::vector, but it is less-  // efficient because it requires an extra memory allocation.-  Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(-      info.Env(),-      nativeArray->data(),-      arrayLength /* size in bytes */,-      [](Napi::Env /*env*/, void* /*data*/, std::vector<uint8_t>* hint) {-        std::unique_ptr<std::vector<uint8_t>> vectorPtrToDelete(hint);-      },-      nativeArray.get());-  // The finalizer is responsible for deleting the vector: release the-  // unique_ptr ownership.-  nativeArray.release();--  Napi::Uint8Array byteArray = Napi::Uint8Array::New(info.Env(), arrayLength, arrayBuffer, 0);-  -  return byteArray;-}--static Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports["AcceptByteArray"] = Napi::Function::New(env, AcceptByteArray);-  exports["CreateByteArray"] = Napi::Function::New(env, CreateByteArray);-  return exports;-}--NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

typed_threadsafe_function/node-addon-api/CMakeLists.txt

deleted file mode 100644@@ -1,23 +0,0 @@-project (clock)-include_directories(${CMAKE_JS_INC} node_modules/node-addon-api/)-cmake_minimum_required(VERSION 3.18)--set(CMAKE_CXX_STANDARD 20)-set(CMAKE_CXX_STANDARD_REQUIRED ON)-include_directories(${CMAKE_JS_INC})-file(GLOB SOURCE_FILES "*.cc")-add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")-target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})--# Include Node-API wrappers-execute_process(COMMAND node -p "require('node-addon-api').include"-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}-        OUTPUT_VARIABLE NODE_ADDON_API_DIR-        )-string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})--target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})--# define NAPI_VERSION-add_definitions(-DNAPI_VERSION=4)

typed_threadsafe_function/node-addon-api/clock.cc

deleted file mode 100644@@ -1,94 +0,0 @@-#include <chrono>-#include <napi.h>-#include <thread>--using namespace Napi;--using Context = Reference<Value>;-using DataType = int;-void CallJs(Napi::Env env, Function callback, Context *context, DataType *data);-using TSFN = TypedThreadSafeFunction<Context, DataType, CallJs>;-using FinalizerDataType = void;--std::thread nativeThread;-TSFN tsfn;--Value Start(const CallbackInfo &info) {-  Napi::Env env = info.Env();--  if (info.Length() < 2) {-    throw TypeError::New(env, "Expected two arguments");-  } else if (!info[0].IsFunction()) {-    throw TypeError::New(env, "Expected first arg to be function");-  } else if (!info[1].IsNumber()) {-    throw TypeError::New(env, "Expected second arg to be number");-  }--  int count = info[1].As<Number>().Int32Value();--  // Create a new context set to the the receiver (ie, `this`) of the function-  // call-  Context *context = new Reference<Value>(Persistent(info.This()));--  // Create a ThreadSafeFunction-  tsfn = TSFN::New(-      env,-      info[0].As<Function>(), // JavaScript function called asynchronously-      "Resource Name",        // Name-      0,                      // Unlimited queue-      1,                      // Only one thread will use this initially-      context,-      [](Napi::Env, FinalizerDataType *,-         Context *ctx) { // Finalizer used to clean threads up-        nativeThread.join();-        delete ctx;-      });--  // Create a native thread-  nativeThread = std::thread([count] {-    for (int i = 0; i < count; i++) {-      // Create new data-      int *value = new int(clock());--      // Perform a blocking call-      napi_status status = tsfn.BlockingCall(value);-      if (status != napi_ok) {-        // Handle error-        break;-      }--      std::this_thread::sleep_for(std::chrono::seconds(1));-    }--    // Release the thread-safe function-    tsfn.Release();-  });--  return Boolean::New(env, true);-}--// Transform native data into JS data, passing it to the provided-// `callback` -- the TSFN's JavaScript function.-void CallJs(Napi::Env env, Function callback, Context *context,-            DataType *data) {-  // Is the JavaScript environment still available to call into, eg. the TSFN is-  // not aborted-  if (env != nullptr) {-    // On Node-API 5+, the `callback` parameter is optional; however, this example-    // does ensure a callback is provided.-    if (callback != nullptr) {-      callback.Call(context->Value(), {Number::New(env, *data)});-    }-  }-  if (data != nullptr) {-    // We're finished with the data.-    delete data;-  }-}--Napi::Object Init(Napi::Env env, Object exports) {-  exports.Set("start", Function::New(env, Start));-  return exports;-}--NODE_API_MODULE(clock, Init)

typed_threadsafe_function/node-addon-api/index.js

deleted file mode 100644@@ -1,6 +0,0 @@-const { start } = require('bindings')('clock');--start.call(new Date(), function (clock) {-    const context = this;-    console.log(context, clock);-}, 5);

typed_threadsafe_function/node-addon-api/package.json

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "name": "example-typedthreadsafefunction",-  "version": "0.0.0",-  "description": "node-addon-api TypedThreadSafeFunction example",-  "main": "index.js",-  "private": true,-  "dependencies": {-    "bindings": "~1.2.1",-    "cmake-js": "^6.1.0",-    "node-addon-api": "^4.0.0"-  },-  "scripts": {-    "test": "node index.js",-    "install": "cmake-js compile"-  },-  "gypfile": true-}

typescript_with_addon/node-addon-api/CMakeLists.txt

deleted file mode 100644@@ -1,26 +0,0 @@-cmake_minimum_required(VERSION 3.9)-set (CMAKE_CXX_STANDARD 11)--project(typescript_with_addon VERSION 0.0.1)-include_directories(${CMAKE_JS_INC})-string(APPEND CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wendif-labels")--file(GLOB SOURCE_FILES *.cpp *.h *.cc *.c)-add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")-target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})--# Include Node-API wrappers-execute_process(COMMAND node -p "require('node-addon-api').include"-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}-        OUTPUT_VARIABLE NODE_ADDON_API_DIR-        )--# need to pay attention to this part-string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})--target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})--# Define NAPI_VERSION-add_definitions(-DNAPI_VERSION=3)-

typescript_with_addon/node-addon-api/README.md

deleted file mode 100644@@ -1,19 +0,0 @@-## TypeScript calls JavaScript that calls C++ that calls C function--### Build and run:--```-npm install -npm test-```--The result:--```-This is a TypeScript class constructor.-This is a Javascript function.-This is a C++ function.-This is a C function.-```--This is using cmake and cmake-js based on the example [build_with_cmake](../build_with_cmake)\ No newline at end of file

typescript_with_addon/node-addon-api/cPart.c

deleted file mode 100644@@ -1,8 +0,0 @@-#include <stdio.h>-#include "cPart.h"--int cPart(int value) {-  int newValue = value + 30;-  printf("I'm a C function and I received %d from C++ and I'm sending back %d \n",value,newValue);-  return newValue;-}\ No newline at end of file

typescript_with_addon/node-addon-api/cPart.h

deleted file mode 100644@@ -1,14 +0,0 @@-#ifndef _C_PART_H_-#define _C_PART_H_--#ifdef __cplusplus-extern "C" {-#endif--int cPart(int);--#ifdef __cplusplus-}  // extern "C"-#endif--#endif

typescript_with_addon/node-addon-api/cppPart.cpp

deleted file mode 100644@@ -1,11 +0,0 @@-#include <iostream>-#include "cPart.h"--using namespace std;--int callingCPart(int value) {-  int result = cPart(++value);-  cout << "I'm a C++ function I'm sending " << value << " to C "-       << "and I received " << result << endl;-  return result;-}\ No newline at end of file

typescript_with_addon/node-addon-api/index.ts

deleted file mode 100644@@ -1,11 +0,0 @@-import {javascriptPart} from './jsPart';--class TypeScriptPart {-  constructor(value:number) {-    console.log('I\'m a TypeScript class constructor I\'m sending',-    value,-    'to JavaScript and I received', javascriptPart(value));-  }-}--new TypeScriptPart(10);\ No newline at end of file

typescript_with_addon/node-addon-api/jsPart.js

deleted file mode 100644@@ -1,16 +0,0 @@-const addon = require('bindings')('typescript_with_addon');--function javascriptPart (value) {-  const result = addon.cppPartExportedByNapi(++value);--  console.log('I\'m a Javascript function and I\'m sending', -  value,-  'to C++ and I received',-  result);--  return result;-}--module.exports = {-  javascriptPart-}\ No newline at end of file

typescript_with_addon/node-addon-api/napiPart.cpp

deleted file mode 100644@@ -1,18 +0,0 @@-#include <napi.h>--extern int callingCPart(int value);--Napi::Value Method(const Napi::CallbackInfo& info) {-  Napi::Env env = info.Env();-  int value = info[0].As<Napi::Number>().Int32Value();-  Napi::Number num = Napi::Number::New(env, callingCPart(value));-  return num;-}--Napi::Object Init(Napi::Env env, Napi::Object exports) {-  exports.Set(Napi::String::New(env, "cppPartExportedByNapi"),-              Napi::Function::New(env, Method));-  return exports;-}--NODE_API_MODULE(cppPartExportedByNapi, Init)\ No newline at end of file

typescript_with_addon/node-addon-api/package.json

deleted file mode 100644@@ -1,17 +0,0 @@-{-  "name": "typescript_with_addon",-  "version": "0.0.0",-  "description": "TypeScript calling Javascript calling C++ calling C with building with CMake and node-addon-api C++ wrapper.",-  "dependencies": {-    "bindings": "^1.5.0",-    "node-addon-api": "^3.0.2"-  },-  "scripts": {-    "install": "npx cmake-js compile",-    "test": "ts-node index.ts"-  },-  "devDependencies": {-    "ts-node": "^9.0.0",-    "typescript": "^5.2.2"-  }-}

typescript_with_addon/node-addon-api/tsconfig.json

deleted file mode 100644@@ -1,7 +0,0 @@-{-  "compilerOptions": {-    "moduleResolution": "node",-    "module": "commonjs"-  }-}-