From e87cf7ef1522463756f0b736f0195004d5a3b217 Mon Sep 17 00:00:00 2001 From: Segev Finer Date: Wed, 28 Feb 2024 00:06:25 +0200 Subject: [PATCH] refactor(bindings)!: convert node bindings to NAPI Co-authored-by: Boris Verkhovskiy Co-authored-by: Amaan Qureshi Co-authored-by: ObserverOfTime --- cli/src/generate/grammar_files.rs | 27 +++++++++++++-------- cli/src/generate/templates/binding.gyp | 12 ++++++++-- cli/src/generate/templates/js-binding.cc | 30 ++++++------------------ cli/src/generate/templates/package.json | 2 +- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/cli/src/generate/grammar_files.rs b/cli/src/generate/grammar_files.rs index af21d561..e437e8b4 100644 --- a/cli/src/generate/grammar_files.rs +++ b/cli/src/generate/grammar_files.rs @@ -193,23 +193,30 @@ pub fn generate_grammar_files( generate_file(path, INDEX_JS_TEMPLATE, language_name) })?; - missing_path(path.join("binding.cc"), |path| { - generate_file(path, JS_BINDING_CC_TEMPLATE, language_name) - })?; + missing_path_else( + path.join("binding.cc"), + |path| generate_file(path, JS_BINDING_CC_TEMPLATE, language_name), + |path| { + let binding_cc = + fs::read_to_string(path).with_context(|| "Failed to read binding.cc")?; + if binding_cc.contains("NAN_METHOD(New) {}") { + eprintln!("Replacing binding.cc with new binding API"); + write_file(path, JS_BINDING_CC_TEMPLATE)?; + } + Ok(()) + }, + )?; - // Create binding.gyp, or update it with new binding path. + // Create binding.gyp, or update it with new binding API. missing_path_else( repo_path.join("binding.gyp"), |path| generate_file(path, BINDING_GYP_TEMPLATE, language_name), |path| { let binding_gyp = fs::read_to_string(path).with_context(|| "Failed to read binding.gyp")?; - let old_path = "\"src/binding.cc\""; - if binding_gyp.contains(old_path) { - eprintln!("Updating binding.gyp with new binding path"); - let binding_gyp = - binding_gyp.replace(old_path, "\"bindings/node/binding.cc\""); - write_file(path, binding_gyp)?; + if binding_gyp.contains("require('nan')") { + eprintln!("Replacing binding.gyp with new binding API"); + write_file(path, BINDING_GYP_TEMPLATE)?; } Ok(()) }, diff --git a/cli/src/generate/templates/binding.gyp b/cli/src/generate/templates/binding.gyp index dd6ced2b..5e8c60ae 100644 --- a/cli/src/generate/templates/binding.gyp +++ b/cli/src/generate/templates/binding.gyp @@ -2,8 +2,8 @@ "targets": [ { "target_name": "tree_sitter_PARSER_NAME_binding", + "dependencies": [" - -using namespace v8; +#include typedef struct TSLanguage TSLanguage; -extern "C" const TSLanguage *tree_sitter_PARSER_NAME(void); +extern "C" TSLanguage *tree_sitter_PARSER_NAME(); -namespace { - -NAN_METHOD(New) {} - -void Init(Local exports, Local module) { - Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("Language").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Local constructor = Nan::GetFunction(tpl).ToLocalChecked(); - Local instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked(); - Nan::SetInternalFieldPointer(instance, 0, (void *)tree_sitter_PARSER_NAME()); - - Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("PARSER_NAME").ToLocalChecked()); - Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); +Napi::Object Init(Napi::Env env, Napi::Object exports) { + exports["name"] = Napi::String::New(env, "PARSER_NAME"); + exports["language"] = Napi::External::New(env, tree_sitter_PARSER_NAME()); + return exports; } -NODE_MODULE_CONTEXT_AWARE(tree_sitter_PARSER_NAME_binding, Init) - -} // namespace +NODE_API_MODULE(tree_sitter_PARSER_NAME_binding, Init) diff --git a/cli/src/generate/templates/package.json b/cli/src/generate/templates/package.json index ec261892..fbc920e5 100644 --- a/cli/src/generate/templates/package.json +++ b/cli/src/generate/templates/package.json @@ -20,7 +20,7 @@ "LOWER_PARSER_NAME" ], "dependencies": { - "nan": "^2.18.0" + "node-addon-api": "^7.1.0" }, "devDependencies": { "tree-sitter-cli": "^CLI_VERSION"