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
Changes to src/5-async-work/call-js-from-async-worker-execute/. All files
src/5-async-work/call-js-from-async-worker-execute/node-addon-api/binding.gyp
@@ -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
@@ -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
@@ -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
@@ -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)