From 0c085cfcd07ec216ca370021e167241efd1b73d7 Mon Sep 17 00:00:00 2001 From: Sampson Gao Date: Tue, 22 Aug 2017 16:59:33 -0400 Subject: [PATCH 1/3] Create a doc for migration --- tools/README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 tools/README.md diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 000000000..8869c53c0 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,63 @@ +# Migration Script + +The migration tool is designed to reduce repetitive work in the migration process. However, the script is not aiming to convert every thing for you. There are usually some small fixes and major reconstruction required. + +### How To Use + +To run the conversion script, first make sure you have the latest `node-addon-api` in your `node_modules` directory. +``` +npm install node-addon-api +``` + +Then run the script passing your project directory +``` +node ./node_modules/node-addon-api/tools/conversion.js ./ +``` + +After finish, recompile and debug things that are missed by the script. + + +### Quick Fixes +Here is the list of things that can be fixed easily. + 1. Change your methods' return value to void if it doesn't return value to JavaScript. + 2. Use `.` to access attribute or to invoke member function in Napi::Object instead of `->`. + 3. `Napi::New(env, value);` to `Napi::[Type]::New(env, value); + + +### Major Reconstructiions +If you use Nan::ObjectWrap in your module, you will need to execute the following steps. + + 1. Convert your [ClassName]::New function to a constructor function. Declare it as +``` +[ClassName](const Napi::CallbackInfo& info); +``` +and define it as +``` +[ClassName]::[ClassName](const Napi::CallbackInfo& info) : Napi::ObjectWrap<[ClassName]>(info){ + ... +} +``` + 2. Move your original constructor code into the new constructor. Delete your original constructor. + 3. In your class initialization function, associate native methods in this way: +``` +Napi::FunctionReference constructor; + +void [ClassName]::Init(Napi::Env env, Napi::Object exports, Napi::Object module) { + Napi::HandleScope scope(env); + Napi::Function ctor = DefineClass(env, "Canvas", { + InstanceMethod("Func1", &[ClassName]::Func1), + InstanceMethod("Func2", &[ClassName]::Func2), + InstanceAccessor("Value", &[ClassName]::ValueGetter]), + StaticMethod("MethodName", &[ClassName]::StaticMethod), + InstanceValue("Value", Napi::[Type]::New(env, value)), + }); + + constructor = Napi::Persistent(ctor); + constructor .SuppressDestruct(); + exports.Set("[ClassName]", ctor); +} +``` + 4. In function where you need to Unwrap the ObjectWrap in NaN like `[ClassName]* native = Nan::ObjectWrap::Unwrap<[ClassName]>(info.This());`, use `this` pointer directly as the unwrapped object. + + +If you still find issues after following this guide, please leave us an issue describing your problem and we will try to resolve it. From 286c7dffbdaeda6734f950a24c2ee8151ea18dea Mon Sep 17 00:00:00 2001 From: Sampson Gao Date: Wed, 23 Aug 2017 14:37:56 -0400 Subject: [PATCH 2/3] Fix a typo --- tools/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/README.md b/tools/README.md index 8869c53c0..f57f06a43 100644 --- a/tools/README.md +++ b/tools/README.md @@ -24,7 +24,7 @@ Here is the list of things that can be fixed easily. 3. `Napi::New(env, value);` to `Napi::[Type]::New(env, value); -### Major Reconstructiions +### Major Reconstructions If you use Nan::ObjectWrap in your module, you will need to execute the following steps. 1. Convert your [ClassName]::New function to a constructor function. Declare it as From a2a79624f59579a70bbb3ce72d910df27a4ecf2a Mon Sep 17 00:00:00 2001 From: Sampson Gao Date: Mon, 16 Oct 2017 10:24:07 -0400 Subject: [PATCH 3/3] Explain difference between Nan::ObjectWrap and Napi::ObjectWrap --- tools/README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/README.md b/tools/README.md index f57f06a43..b0a9a2bf8 100644 --- a/tools/README.md +++ b/tools/README.md @@ -25,9 +25,11 @@ Here is the list of things that can be fixed easily. ### Major Reconstructions -If you use Nan::ObjectWrap in your module, you will need to execute the following steps. +The implementation of `Napi::ObjectWrap` is significantly different from NAN's. `Napi::ObjectWrap` takes a pointer to the wrapped object and creates a reference to the wrapped object inside ObjectWrap constructor. `Napi::ObjectWrap` also associated wrapped object's instance methods to Javascript module instead of static methods like NAN. - 1. Convert your [ClassName]::New function to a constructor function. Declare it as +So if you use Nan::ObjectWrap in your module, you will need to execute the following steps. + + 1. Convert your [ClassName]::New function to a constructor function that takes a `Napi::CallbackInfo`. Declare it as ``` [ClassName](const Napi::CallbackInfo& info); ``` @@ -37,8 +39,10 @@ and define it as ... } ``` +This way, the `Napi::ObjectWrap` constructor will be invoked after the object has been instanciated and `Napi::ObjectWrap` can use the `this` pointer to create reference to the wrapped object. + 2. Move your original constructor code into the new constructor. Delete your original constructor. - 3. In your class initialization function, associate native methods in this way: + 3. In your class initialization function, associate native methods in the following way. The `&` character before methods is required because they are not static methods but instance methods. ``` Napi::FunctionReference constructor; @@ -47,7 +51,7 @@ void [ClassName]::Init(Napi::Env env, Napi::Object exports, Napi::Object module) Napi::Function ctor = DefineClass(env, "Canvas", { InstanceMethod("Func1", &[ClassName]::Func1), InstanceMethod("Func2", &[ClassName]::Func2), - InstanceAccessor("Value", &[ClassName]::ValueGetter]), + InstanceAccessor("Value", &[ClassName]::ValueGetter), StaticMethod("MethodName", &[ClassName]::StaticMethod), InstanceValue("Value", Napi::[Type]::New(env, value)), }); @@ -57,7 +61,7 @@ void [ClassName]::Init(Napi::Env env, Napi::Object exports, Napi::Object module) exports.Set("[ClassName]", ctor); } ``` - 4. In function where you need to Unwrap the ObjectWrap in NaN like `[ClassName]* native = Nan::ObjectWrap::Unwrap<[ClassName]>(info.This());`, use `this` pointer directly as the unwrapped object. + 4. In function where you need to Unwrap the ObjectWrap in NAN like `[ClassName]* native = Nan::ObjectWrap::Unwrap<[ClassName]>(info.This());`, use `this` pointer directly as the unwrapped object as each ObjectWrap instance is associated with a unique object instance. If you still find issues after following this guide, please leave us an issue describing your problem and we will try to resolve it.