diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c72ba30d..658af321 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,8 +12,8 @@ on: - released env: - NODE_PREBUILD_CMD: npx prebuild -t 10.0.0 -t 12.0.0 -t 14.0.0 -t 16.0.0 -t 18.0.0 -t 20.0.0 --strip -u ${{ secrets.GH_TOKEN }} - ELECTRON_PREBUILD_CMD: npx prebuild -r electron -t 3.0.0 -t 4.0.0 -t 5.0.0 -t 6.0.0 -t 7.0.0 -t 8.0.0 -t 9.0.0 -t 10.0.0 -t 11.0.0 -t 12.0.0 -t 13.0.0 -t 14.0.0 -t 15.0.0 -t 16.0.0 -t 17.0.0 -t 18.0.0 -t 19.0.0 -t 20.0.0 -t 21.0.0 -t 22.0.0 -t 23.0.0 -t 24.0.0 -t 25.0.0 --strip -u ${{ secrets.GH_TOKEN }} + NODE_PREBUILD_CMD: npx prebuild -t 14.0.0 -t 16.0.0 -t 18.0.0 -t 20.0.0 --strip -u ${{ secrets.GH_TOKEN }} + ELECTRON_PREBUILD_CMD: npx prebuild -r electron -t 12.0.0 -t 13.0.0 -t 14.0.0 -t 15.0.0 -t 16.0.0 -t 17.0.0 -t 18.0.0 -t 19.0.0 -t 20.0.0 -t 21.0.0 -t 22.0.0 -t 23.0.0 -t 24.0.0 -t 25.0.0 --strip -u ${{ secrets.GH_TOKEN }} jobs: @@ -25,8 +25,6 @@ jobs: - macos-latest - ubuntu-20.04 node: - - 10 - - 12 - 14 - 16 - 18 diff --git a/src/addon_data.h b/src/addon_data.h new file mode 100644 index 00000000..9700d14a --- /dev/null +++ b/src/addon_data.h @@ -0,0 +1,59 @@ +#include +#include +#include + +#ifndef NODE_TREE_SITTER_ADDON_DATA_H_ +#define NODE_TREE_SITTER_ADDON_DATA_H_ + +namespace node_tree_sitter { + +class AddonData { +public: + explicit AddonData(v8::Isolate* isolate) { + // Ensure this per-addon-instance data is deleted at environment cleanup. + node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this); + } + + ~AddonData() { + ts_query_cursor_delete(ts_query_cursor); + } + + // conversions + Nan::Persistent row_key; + Nan::Persistent column_key; + Nan::Persistent start_index_key; + Nan::Persistent start_position_key; + Nan::Persistent end_index_key; + Nan::Persistent end_position_key; + uint32_t *point_transfer_buffer = nullptr; + + // node + uint32_t *transfer_buffer = nullptr; + uint32_t transfer_buffer_length = 0; + Nan::Persistent module_exports; + TSTreeCursor scratch_cursor = {nullptr, nullptr, {0, 0}}; + + // parser + Nan::Persistent parser_constructor; + + // query + TSQueryCursor *ts_query_cursor = nullptr; + Nan::Persistent query_constructor; + Nan::Persistent query_constructor_template; + + // tree_cursor + Nan::Persistent tree_cursor_constructor; + + // tree + Nan::Persistent tree_constructor; + Nan::Persistent tree_constructor_template; + +private: + static void DeleteInstance(void* data) { + delete static_cast(data); + } +}; + +} + +#endif // NODE_TREE_SITTER_ADDON_DATA_H_ diff --git a/src/binding.cc b/src/binding.cc index 7db7ebe4..31868827 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -1,5 +1,6 @@ #include #include +#include "./addon_data.h" #include "./language.h" #include "./node.h" #include "./parser.h" @@ -12,16 +13,22 @@ namespace node_tree_sitter { using namespace v8; -void InitAll(Local exports, Local m_, void* v_) { - InitConversions(exports); - node_methods::Init(exports); +void InitAll(Local exports, Local m_, Local context) { + Isolate* isolate = context->GetIsolate(); + + AddonData* data = new AddonData(isolate); + + Local data_ext = External::New(isolate, data); + + InitConversions(exports, data_ext); + node_methods::Init(exports, data_ext); language_methods::Init(exports); - Parser::Init(exports); - Query::Init(exports); - Tree::Init(exports); - TreeCursor::Init(exports); + Parser::Init(exports, data_ext); + Query::Init(exports, data_ext); + Tree::Init(exports, data_ext); + TreeCursor::Init(exports, data_ext); } -NODE_MODULE(tree_sitter_runtime_binding, InitAll) +NODE_MODULE_CONTEXT_AWARE(tree_sitter_runtime_binding, InitAll) } // namespace node_tree_sitter diff --git a/src/conversions.cc b/src/conversions.cc index 5e8eb424..6551cd86 100644 --- a/src/conversions.cc +++ b/src/conversions.cc @@ -1,4 +1,5 @@ #include "./node.h" +#include "./addon_data.h" #include #include #include @@ -9,54 +10,39 @@ namespace node_tree_sitter { using namespace v8; -Nan::Persistent row_key; -Nan::Persistent column_key; -Nan::Persistent start_index_key; -Nan::Persistent start_position_key; -Nan::Persistent end_index_key; -Nan::Persistent end_position_key; - -static unsigned BYTES_PER_CHARACTER = 2; -static uint32_t *point_transfer_buffer; - -void InitConversions(Local exports) { - row_key.Reset(Nan::Persistent(Nan::New("row").ToLocalChecked())); - column_key.Reset(Nan::Persistent(Nan::New("column").ToLocalChecked())); - start_index_key.Reset(Nan::Persistent(Nan::New("startIndex").ToLocalChecked())); - start_position_key.Reset(Nan::Persistent(Nan::New("startPosition").ToLocalChecked())); - end_index_key.Reset(Nan::Persistent(Nan::New("endIndex").ToLocalChecked())); - end_position_key.Reset(Nan::Persistent(Nan::New("endPosition").ToLocalChecked())); - - #if defined(_MSC_VER) && NODE_RUNTIME_ELECTRON && NODE_MODULE_VERSION >= 89 - auto js_point_transfer_buffer = ArrayBuffer::New(Isolate::GetCurrent(), 2 * sizeof(uint32_t)); - point_transfer_buffer = (uint32_t *)(js_point_transfer_buffer->Data()); - #elif V8_MAJOR_VERSION < 8 || (V8_MAJOR_VERSION == 8 && V8_MINOR_VERSION < 4) || (defined(_MSC_VER) && NODE_RUNTIME_ELECTRON) - point_transfer_buffer = static_cast(malloc(2 * sizeof(uint32_t))); - auto js_point_transfer_buffer = ArrayBuffer::New(Isolate::GetCurrent(), point_transfer_buffer, 2 * sizeof(uint32_t)); - #else - point_transfer_buffer = static_cast(malloc(2 * sizeof(uint32_t))); - auto backing_store = ArrayBuffer::NewBackingStore(point_transfer_buffer, 2 * sizeof(uint32_t), BackingStore::EmptyDeleter, nullptr); - auto js_point_transfer_buffer = ArrayBuffer::New(Isolate::GetCurrent(), std::move(backing_store)); - #endif - - Nan::Set(exports, Nan::New("pointTransferArray").ToLocalChecked(), Uint32Array::New(js_point_transfer_buffer, 0, 2)); +static const unsigned BYTES_PER_CHARACTER = 2; + +void InitConversions(Local exports, Local data_ext) { + AddonData* data = static_cast(data_ext->Value()); + + data->row_key.Reset(Nan::Persistent(Nan::New("row").ToLocalChecked())); + data->column_key.Reset(Nan::Persistent(Nan::New("column").ToLocalChecked())); + data->start_index_key.Reset(Nan::Persistent(Nan::New("startIndex").ToLocalChecked())); + data->start_position_key.Reset(Nan::Persistent(Nan::New("startPosition").ToLocalChecked())); + data->end_index_key.Reset(Nan::Persistent(Nan::New("endIndex").ToLocalChecked())); + data->end_position_key.Reset(Nan::Persistent(Nan::New("endPosition").ToLocalChecked())); + + auto js_point_transfer_buffer = Nan::NewBuffer(2 * sizeof(uint32_t)).ToLocalChecked(); + data->point_transfer_buffer = reinterpret_cast(node::Buffer::Data(js_point_transfer_buffer)); + + Nan::Set(exports, Nan::New("pointTransferArray").ToLocalChecked(), Uint32Array::New(js_point_transfer_buffer.As()->Buffer(), 0, 2)); } -void TransferPoint(const TSPoint &point) { - point_transfer_buffer[0] = point.row; - point_transfer_buffer[1] = point.column / 2; +void TransferPoint(AddonData* data, const TSPoint &point) { + data->point_transfer_buffer[0] = point.row; + data->point_transfer_buffer[1] = point.column / 2; } -Local RangeToJS(const TSRange &range) { +Local RangeToJS(AddonData* data, const TSRange &range) { Local result = Nan::New(); - Nan::Set(result, Nan::New(start_position_key), PointToJS(range.start_point)); - Nan::Set(result, Nan::New(start_index_key), ByteCountToJS(range.start_byte)); - Nan::Set(result, Nan::New(end_position_key), PointToJS(range.end_point)); - Nan::Set(result, Nan::New(end_index_key), ByteCountToJS(range.end_byte)); + Nan::Set(result, Nan::New(data->start_position_key), PointToJS(data, range.start_point)); + Nan::Set(result, Nan::New(data->start_index_key), ByteCountToJS(data, range.start_byte)); + Nan::Set(result, Nan::New(data->end_position_key), PointToJS(data, range.end_point)); + Nan::Set(result, Nan::New(data->end_index_key), ByteCountToJS(data, range.end_byte)); return result; } -Nan::Maybe RangeFromJS(const Local &arg) { +Nan::Maybe RangeFromJS(AddonData* data, const Local &arg) { if (!arg->IsObject()) { Nan::ThrowTypeError("Range must be a {startPosition, endPosition, startIndex, endIndex} object"); return Nan::Nothing(); @@ -72,7 +58,7 @@ Nan::Maybe RangeFromJS(const Local &arg) { Nan::ThrowTypeError("Range must be a {startPosition, endPosition, startIndex, endIndex} object"); \ return Nan::Nothing(); \ } \ - auto field = Convert(value.ToLocalChecked()); \ + auto field = Convert(data, value.ToLocalChecked()); \ if (field.IsJust()) { \ result.field = field.FromJust(); \ } else { \ @@ -80,24 +66,24 @@ Nan::Maybe RangeFromJS(const Local &arg) { } \ } - INIT(start_point, start_position_key, PointFromJS); - INIT(end_point, end_position_key, PointFromJS); - INIT(start_byte, start_index_key, ByteCountFromJS); - INIT(end_byte, end_index_key, ByteCountFromJS); + INIT(start_point, data->start_position_key, PointFromJS); + INIT(end_point, data->end_position_key, PointFromJS); + INIT(start_byte, data->start_index_key, ByteCountFromJS); + INIT(end_byte, data->end_index_key, ByteCountFromJS); #undef INIT return Nan::Just(result); } -Local PointToJS(const TSPoint &point) { +Local PointToJS(AddonData* data, const TSPoint &point) { Local result = Nan::New(); - Nan::Set(result, Nan::New(row_key), Nan::New(point.row)); - Nan::Set(result, Nan::New(column_key), ByteCountToJS(point.column)); + Nan::Set(result, Nan::New(data->row_key), Nan::New(point.row)); + Nan::Set(result, Nan::New(data->column_key), ByteCountToJS(data, point.column)); return result; } -Nan::Maybe PointFromJS(const Local &arg) { +Nan::Maybe PointFromJS(AddonData* data, const Local &arg) { Local js_point; if (!arg->IsObject() || !Nan::To(arg).ToLocal(&js_point)) { Nan::ThrowTypeError("Point must be a {row, column} object"); @@ -105,13 +91,13 @@ Nan::Maybe PointFromJS(const Local &arg) { } Local js_row; - if (!Nan::Get(js_point, Nan::New(row_key)).ToLocal(&js_row)) { + if (!Nan::Get(js_point, Nan::New(data->row_key)).ToLocal(&js_row)) { Nan::ThrowTypeError("Point must be a {row, column} object"); return Nan::Nothing(); } Local js_column; - if (!Nan::Get(js_point, Nan::New(column_key)).ToLocal(&js_column)) { + if (!Nan::Get(js_point, Nan::New(data->column_key)).ToLocal(&js_column)) { Nan::ThrowTypeError("Point must be a {row, column} object"); return Nan::Nothing(); } @@ -139,11 +125,11 @@ Nan::Maybe PointFromJS(const Local &arg) { return Nan::Just({row, column}); } -Local ByteCountToJS(uint32_t byte_count) { +Local ByteCountToJS(AddonData* data, uint32_t byte_count) { return Nan::New(byte_count / BYTES_PER_CHARACTER); } -Nan::Maybe ByteCountFromJS(const v8::Local &arg) { +Nan::Maybe ByteCountFromJS(AddonData* data, const v8::Local &arg) { auto result = Nan::To(arg); if (!arg->IsNumber()) { Nan::ThrowTypeError("Character index must be a number"); diff --git a/src/conversions.h b/src/conversions.h index 69bcfb51..38b1c62c 100644 --- a/src/conversions.h +++ b/src/conversions.h @@ -4,22 +4,18 @@ #include #include #include +#include "./addon_data.h" namespace node_tree_sitter { -void InitConversions(v8::Local exports); -v8::Local RangeToJS(const TSRange &); -v8::Local PointToJS(const TSPoint &); -void TransferPoint(const TSPoint &); -v8::Local ByteCountToJS(uint32_t); -Nan::Maybe PointFromJS(const v8::Local &); -Nan::Maybe ByteCountFromJS(const v8::Local &); -Nan::Maybe RangeFromJS(const v8::Local &); - -extern Nan::Persistent row_key; -extern Nan::Persistent column_key; -extern Nan::Persistent start_key; -extern Nan::Persistent end_key; +void InitConversions(v8::Local exports, v8::Local data_ext); +v8::Local RangeToJS(AddonData* data, const TSRange &); +v8::Local PointToJS(AddonData* data, const TSPoint &); +void TransferPoint(AddonData* data, const TSPoint &); +v8::Local ByteCountToJS(AddonData* data, uint32_t); +Nan::Maybe PointFromJS(AddonData* data, const v8::Local &); +Nan::Maybe ByteCountFromJS(AddonData* data, const v8::Local &); +Nan::Maybe RangeFromJS(AddonData* data, const v8::Local &); } // namespace node_tree_sitter diff --git a/src/node.cc b/src/node.cc index 51760499..1f93fe7a 100644 --- a/src/node.cc +++ b/src/node.cc @@ -16,34 +16,18 @@ using namespace v8; static const uint32_t FIELD_COUNT_PER_NODE = 6; -static uint32_t *transfer_buffer = nullptr; -static uint32_t transfer_buffer_length = 0; -static Nan::Persistent module_exports; -static TSTreeCursor scratch_cursor = {nullptr, nullptr, {0, 0}}; - -static inline void setup_transfer_buffer(uint32_t node_count) { +static inline void setup_transfer_buffer(AddonData* data, uint32_t node_count) { uint32_t new_length = node_count * FIELD_COUNT_PER_NODE; - if (new_length > transfer_buffer_length) { - transfer_buffer_length = new_length; - - #if defined(_MSC_VER) && NODE_RUNTIME_ELECTRON && NODE_MODULE_VERSION >= 89 - auto js_transfer_buffer = ArrayBuffer::New(Isolate::GetCurrent(), transfer_buffer_length * sizeof(uint32_t)); - transfer_buffer = (uint32_t *)(js_transfer_buffer->Data()); - #elif V8_MAJOR_VERSION < 8 || (V8_MAJOR_VERSION == 8 && V8_MINOR_VERSION < 4) || (defined(_MSC_VER) && NODE_RUNTIME_ELECTRON) - if (transfer_buffer) { free(transfer_buffer); } - transfer_buffer = static_cast(malloc(transfer_buffer_length * sizeof(uint32_t))); - auto js_transfer_buffer = ArrayBuffer::New(Isolate::GetCurrent(), transfer_buffer, transfer_buffer_length * sizeof(uint32_t)); - #else - if (transfer_buffer) { free(transfer_buffer); } - transfer_buffer = static_cast(malloc(transfer_buffer_length * sizeof(uint32_t))); - auto backing_store = ArrayBuffer::NewBackingStore(transfer_buffer, transfer_buffer_length * sizeof(uint32_t), BackingStore::EmptyDeleter, nullptr); - auto js_transfer_buffer = ArrayBuffer::New(Isolate::GetCurrent(), std::move(backing_store)); - #endif + if (new_length > data->transfer_buffer_length) { + data->transfer_buffer_length = new_length; + + auto js_transfer_buffer = Nan::NewBuffer(data->transfer_buffer_length * sizeof(uint32_t)).ToLocalChecked(); + data->transfer_buffer = reinterpret_cast(node::Buffer::Data(js_transfer_buffer)); Nan::Set( - Nan::New(module_exports), + Nan::New(data->module_exports), Nan::New("nodeTransferArray").ToLocalChecked(), - Uint32Array::New(js_transfer_buffer, 0, transfer_buffer_length) + Uint32Array::New(js_transfer_buffer.As()->Buffer(), 0, data->transfer_buffer_length) ); } } @@ -65,9 +49,10 @@ void MarshalNode(const Nan::FunctionCallbackInfo &info, const Tree *tree, Local GetMarshalNodes(const Nan::FunctionCallbackInfo &info, const Tree *tree, const TSNode *nodes, uint32_t node_count) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); auto result = Nan::New(); - setup_transfer_buffer(node_count); - uint32_t *p = transfer_buffer; + setup_transfer_buffer(data, node_count); + uint32_t *p = data->transfer_buffer; for (unsigned i = 0; i < node_count; i++) { TSNode node = nodes[i]; const auto &cache_entry = tree->cached_nodes_.find(node.id); @@ -91,10 +76,11 @@ Local GetMarshalNodes(const Nan::FunctionCallbackInfo &info, } Local GetMarshalNode(const Nan::FunctionCallbackInfo &info, const Tree *tree, TSNode node) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); const auto &cache_entry = tree->cached_nodes_.find(node.id); if (cache_entry == tree->cached_nodes_.end()) { - setup_transfer_buffer(1); - uint32_t *p = transfer_buffer; + setup_transfer_buffer(data, 1); + uint32_t *p = data->transfer_buffer; MarshalNodeId(node.id, p); p += 2; *(p++) = node.context[0]; @@ -110,11 +96,11 @@ Local GetMarshalNode(const Nan::FunctionCallbackInfo &info, const return Nan::Null(); } -void MarshalNullNode() { - memset(transfer_buffer, 0, FIELD_COUNT_PER_NODE * sizeof(transfer_buffer[0])); +void MarshalNullNode(AddonData* data) { + memset(data->transfer_buffer, 0, FIELD_COUNT_PER_NODE * sizeof(data->transfer_buffer[0])); } -TSNode UnmarshalNode(const Tree *tree) { +TSNode UnmarshalNode(AddonData* data, const Tree *tree) { TSNode result = {{0, 0, 0, 0}, nullptr, nullptr}; result.tree = tree->tree_; if (!result.tree) { @@ -122,17 +108,18 @@ TSNode UnmarshalNode(const Tree *tree) { return result; } - result.id = UnmarshalNodeId(&transfer_buffer[0]); - result.context[0] = transfer_buffer[2]; - result.context[1] = transfer_buffer[3]; - result.context[2] = transfer_buffer[4]; - result.context[3] = transfer_buffer[5]; + result.id = UnmarshalNodeId(&data->transfer_buffer[0]); + result.context[0] = data->transfer_buffer[2]; + result.context[1] = data->transfer_buffer[3]; + result.context[2] = data->transfer_buffer[4]; + result.context[3] = data->transfer_buffer[5]; return result; } static void ToString(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { const char *string = ts_node_string(node); info.GetReturnValue().Set(Nan::New(string).ToLocalChecked()); @@ -141,8 +128,9 @@ static void ToString(const Nan::FunctionCallbackInfo &info) { } static void IsMissing(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { bool result = ts_node_is_missing(node); info.GetReturnValue().Set(Nan::New(result)); @@ -150,8 +138,9 @@ static void IsMissing(const Nan::FunctionCallbackInfo &info) { } static void HasChanges(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { bool result = ts_node_has_changes(node); info.GetReturnValue().Set(Nan::New(result)); @@ -159,8 +148,9 @@ static void HasChanges(const Nan::FunctionCallbackInfo &info) { } static void HasError(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { bool result = ts_node_has_error(node); info.GetReturnValue().Set(Nan::New(result)); @@ -168,39 +158,42 @@ static void HasError(const Nan::FunctionCallbackInfo &info) { } static void FirstNamedChildForIndex(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { - Nan::Maybe byte = ByteCountFromJS(info[1]); + Nan::Maybe byte = ByteCountFromJS(data, info[1]); if (byte.IsJust()) { MarshalNode(info, tree, ts_node_first_named_child_for_byte(node, byte.FromJust())); return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void FirstChildForIndex(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id && info.Length() > 1) { - Nan::Maybe byte = ByteCountFromJS(info[1]); + Nan::Maybe byte = ByteCountFromJS(data, info[1]); if (byte.IsJust()) { MarshalNode(info, tree, ts_node_first_child_for_byte(node, byte.FromJust())); return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void NamedDescendantForIndex(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { - Nan::Maybe maybe_min = ByteCountFromJS(info[1]); - Nan::Maybe maybe_max = ByteCountFromJS(info[2]); + Nan::Maybe maybe_min = ByteCountFromJS(data, info[1]); + Nan::Maybe maybe_max = ByteCountFromJS(data, info[2]); if (maybe_min.IsJust() && maybe_max.IsJust()) { uint32_t min = maybe_min.FromJust(); uint32_t max = maybe_max.FromJust(); @@ -208,16 +201,17 @@ static void NamedDescendantForIndex(const Nan::FunctionCallbackInfo &info return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void DescendantForIndex(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { - Nan::Maybe maybe_min = ByteCountFromJS(info[1]); - Nan::Maybe maybe_max = ByteCountFromJS(info[2]); + Nan::Maybe maybe_min = ByteCountFromJS(data, info[1]); + Nan::Maybe maybe_max = ByteCountFromJS(data, info[2]); if (maybe_min.IsJust() && maybe_max.IsJust()) { uint32_t min = maybe_min.FromJust(); uint32_t max = maybe_max.FromJust(); @@ -225,16 +219,17 @@ static void DescendantForIndex(const Nan::FunctionCallbackInfo &info) { return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void NamedDescendantForPosition(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { - Nan::Maybe maybe_min = PointFromJS(info[1]); - Nan::Maybe maybe_max = PointFromJS(info[2]); + Nan::Maybe maybe_min = PointFromJS(data, info[1]); + Nan::Maybe maybe_max = PointFromJS(data, info[2]); if (maybe_min.IsJust() && maybe_max.IsJust()) { TSPoint min = maybe_min.FromJust(); TSPoint max = maybe_max.FromJust(); @@ -242,16 +237,17 @@ static void NamedDescendantForPosition(const Nan::FunctionCallbackInfo &i return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void DescendantForPosition(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { - Nan::Maybe maybe_min = PointFromJS(info[1]); - Nan::Maybe maybe_max = PointFromJS(info[2]); + Nan::Maybe maybe_min = PointFromJS(data, info[1]); + Nan::Maybe maybe_max = PointFromJS(data, info[2]); if (maybe_min.IsJust() && maybe_max.IsJust()) { TSPoint min = maybe_min.FromJust(); TSPoint max = maybe_max.FromJust(); @@ -259,12 +255,13 @@ static void DescendantForPosition(const Nan::FunctionCallbackInfo &info) return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void Type(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { const char *result = ts_node_type(node); @@ -273,8 +270,9 @@ static void Type(const Nan::FunctionCallbackInfo &info) { } static void TypeId(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { TSSymbol result = ts_node_symbol(node); @@ -283,8 +281,9 @@ static void TypeId(const Nan::FunctionCallbackInfo &info) { } static void IsNamed(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { bool result = ts_node_is_named(node); @@ -293,8 +292,9 @@ static void IsNamed(const Nan::FunctionCallbackInfo &info) { } static void StartIndex(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { int32_t result = ts_node_start_byte(node) / 2; @@ -303,8 +303,9 @@ static void StartIndex(const Nan::FunctionCallbackInfo &info) { } static void EndIndex(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { int32_t result = ts_node_end_byte(node) / 2; @@ -313,26 +314,29 @@ static void EndIndex(const Nan::FunctionCallbackInfo &info) { } static void StartPosition(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { - TransferPoint(ts_node_start_point(node)); + TransferPoint(data, ts_node_start_point(node)); } } static void EndPosition(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { - TransferPoint(ts_node_end_point(node)); + TransferPoint(data, ts_node_end_point(node)); } } static void Child(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { if (!info[1]->IsUint32()) { @@ -343,12 +347,13 @@ static void Child(const Nan::FunctionCallbackInfo &info) { MarshalNode(info, tree, ts_node_child(node, index)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void NamedChild(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { if (!info[1]->IsUint32()) { @@ -359,12 +364,13 @@ static void NamedChild(const Nan::FunctionCallbackInfo &info) { MarshalNode(info, tree, ts_node_named_child(node, index)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void ChildCount(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { info.GetReturnValue().Set(Nan::New(ts_node_child_count(node))); @@ -372,8 +378,9 @@ static void ChildCount(const Nan::FunctionCallbackInfo &info) { } static void NamedChildCount(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { info.GetReturnValue().Set(Nan::New(ts_node_named_child_count(node))); @@ -381,28 +388,31 @@ static void NamedChildCount(const Nan::FunctionCallbackInfo &info) { } static void FirstChild(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { MarshalNode(info, tree, ts_node_child(node, 0)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void FirstNamedChild(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { MarshalNode(info, tree, ts_node_named_child(node, 0)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void LastChild(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { uint32_t child_count = ts_node_child_count(node); if (child_count > 0) { @@ -410,12 +420,13 @@ static void LastChild(const Nan::FunctionCallbackInfo &info) { return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void LastNamedChild(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { uint32_t child_count = ts_node_named_child_count(node); if (child_count > 0) { @@ -423,57 +434,62 @@ static void LastNamedChild(const Nan::FunctionCallbackInfo &info) { return; } } - MarshalNullNode(); + MarshalNullNode(data); } static void Parent(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { MarshalNode(info, tree, ts_node_parent(node)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void NextSibling(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { MarshalNode(info, tree, ts_node_next_sibling(node)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void NextNamedSibling(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { MarshalNode(info, tree, ts_node_next_named_sibling(node)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void PreviousSibling(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { MarshalNode(info, tree, ts_node_prev_sibling(node)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void PreviousNamedSibling(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { MarshalNode(info, tree, ts_node_prev_named_sibling(node)); return; } - MarshalNullNode(); + MarshalNullNode(data); } struct SymbolSet { @@ -535,44 +551,47 @@ bool symbol_set_from_js(SymbolSet *symbols, const Local &value, const TSL } static void Children(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (!node.id) return; vector result; - ts_tree_cursor_reset(&scratch_cursor, node); - if (ts_tree_cursor_goto_first_child(&scratch_cursor)) { + ts_tree_cursor_reset(&data->scratch_cursor, node); + if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { do { - TSNode child = ts_tree_cursor_current_node(&scratch_cursor); + TSNode child = ts_tree_cursor_current_node(&data->scratch_cursor); result.push_back(child); - } while (ts_tree_cursor_goto_next_sibling(&scratch_cursor)); + } while (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)); } MarshalNodes(info, tree, result.data(), result.size()); } static void NamedChildren(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (!node.id) return; vector result; - ts_tree_cursor_reset(&scratch_cursor, node); - if (ts_tree_cursor_goto_first_child(&scratch_cursor)) { + ts_tree_cursor_reset(&data->scratch_cursor, node); + if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { do { - TSNode child = ts_tree_cursor_current_node(&scratch_cursor); + TSNode child = ts_tree_cursor_current_node(&data->scratch_cursor); if (ts_node_is_named(child)) { result.push_back(child); } - } while (ts_tree_cursor_goto_next_sibling(&scratch_cursor)); + } while (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)); } MarshalNodes(info, tree, result.data(), result.size()); } static void DescendantsOfType(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (!node.id) return; SymbolSet symbols; @@ -582,29 +601,29 @@ static void DescendantsOfType(const Nan::FunctionCallbackInfo &info) { TSPoint end_point = {UINT32_MAX, UINT32_MAX}; if (info.Length() > 2 && info[2]->IsObject()) { - auto maybe_start_point = PointFromJS(info[2]); + auto maybe_start_point = PointFromJS(data, info[2]); if (maybe_start_point.IsNothing()) return; start_point = maybe_start_point.FromJust(); } if (info.Length() > 3 && info[3]->IsObject()) { - auto maybe_end_point = PointFromJS(info[3]); + auto maybe_end_point = PointFromJS(data, info[3]); if (maybe_end_point.IsNothing()) return; end_point = maybe_end_point.FromJust(); } vector found; - ts_tree_cursor_reset(&scratch_cursor, node); + ts_tree_cursor_reset(&data->scratch_cursor, node); auto already_visited_children = false; while (true) { - TSNode descendant = ts_tree_cursor_current_node(&scratch_cursor); + TSNode descendant = ts_tree_cursor_current_node(&data->scratch_cursor); if (!already_visited_children) { if (ts_node_end_point(descendant) <= start_point) { - if (ts_tree_cursor_goto_next_sibling(&scratch_cursor)) { + if (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)) { already_visited_children = false; } else { - if (!ts_tree_cursor_goto_parent(&scratch_cursor)) break; + if (!ts_tree_cursor_goto_parent(&data->scratch_cursor)) break; already_visited_children = true; } continue; @@ -616,19 +635,19 @@ static void DescendantsOfType(const Nan::FunctionCallbackInfo &info) { found.push_back(descendant); } - if (ts_tree_cursor_goto_first_child(&scratch_cursor)) { + if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { already_visited_children = false; - } else if (ts_tree_cursor_goto_next_sibling(&scratch_cursor)) { + } else if (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)) { already_visited_children = false; } else { - if (!ts_tree_cursor_goto_parent(&scratch_cursor)) break; + if (!ts_tree_cursor_goto_parent(&data->scratch_cursor)) break; already_visited_children = true; } } else { - if (ts_tree_cursor_goto_next_sibling(&scratch_cursor)) { + if (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)) { already_visited_children = false; } else { - if (!ts_tree_cursor_goto_parent(&scratch_cursor)) break; + if (!ts_tree_cursor_goto_parent(&data->scratch_cursor)) break; } } } @@ -637,8 +656,9 @@ static void DescendantsOfType(const Nan::FunctionCallbackInfo &info) { } static void ChildNodesForFieldId(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (!node.id) return; auto maybe_field_id = Nan::To(info[1]); @@ -649,22 +669,23 @@ static void ChildNodesForFieldId(const Nan::FunctionCallbackInfo &info) { uint32_t field_id = maybe_field_id.FromJust(); vector result; - ts_tree_cursor_reset(&scratch_cursor, node); - if (ts_tree_cursor_goto_first_child(&scratch_cursor)) { + ts_tree_cursor_reset(&data->scratch_cursor, node); + if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { do { - TSNode child = ts_tree_cursor_current_node(&scratch_cursor); - if (ts_tree_cursor_current_field_id(&scratch_cursor) == field_id) { + TSNode child = ts_tree_cursor_current_node(&data->scratch_cursor); + if (ts_tree_cursor_current_field_id(&data->scratch_cursor) == field_id) { result.push_back(child); } - } while (ts_tree_cursor_goto_next_sibling(&scratch_cursor)); + } while (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)); } MarshalNodes(info, tree, result.data(), result.size()); } static void ChildNodeForFieldId(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (node.id) { auto maybe_field_id = Nan::To(info[1]); @@ -676,12 +697,13 @@ static void ChildNodeForFieldId(const Nan::FunctionCallbackInfo &info) { MarshalNode(info, tree, ts_node_child_by_field_id(node, field_id)); return; } - MarshalNullNode(); + MarshalNullNode(data); } static void Closest(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); if (!node.id) return; SymbolSet symbols; @@ -697,17 +719,20 @@ static void Closest(const Nan::FunctionCallbackInfo &info) { node = parent; } - MarshalNullNode(); + MarshalNullNode(data); } static void Walk(const Nan::FunctionCallbackInfo &info) { - const Tree *tree = Tree::UnwrapTree(info[0]); - TSNode node = UnmarshalNode(tree); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); + TSNode node = UnmarshalNode(data, tree); TSTreeCursor cursor = ts_tree_cursor_new(node); - info.GetReturnValue().Set(TreeCursor::NewInstance(cursor)); + info.GetReturnValue().Set(TreeCursor::NewInstance(data, cursor)); } -void Init(Local exports) { +void Init(Local exports, Local data_ext) { + AddonData* data = reinterpret_cast(data_ext->Value()); + Local result = Nan::New(); FunctionPair methods[] = { @@ -754,12 +779,12 @@ void Init(Local exports) { Nan::Set( result, Nan::New(methods[i].name).ToLocalChecked(), - Nan::GetFunction(Nan::New(methods[i].callback)).ToLocalChecked() + Nan::GetFunction(Nan::New(methods[i].callback, data_ext)).ToLocalChecked() ); } - module_exports.Reset(exports); - setup_transfer_buffer(1); + data->module_exports.Reset(exports); + setup_transfer_buffer(data, 1); Nan::Set(exports, Nan::New("NodeMethods").ToLocalChecked(), result); } diff --git a/src/node.h b/src/node.h index 8c050e20..872fa14b 100644 --- a/src/node.h +++ b/src/node.h @@ -12,11 +12,11 @@ using namespace v8; namespace node_tree_sitter { namespace node_methods { -void Init(v8::Local); +void Init(v8::Local, v8::Local); void MarshalNode(const Nan::FunctionCallbackInfo &info, const Tree *, TSNode); Local GetMarshalNode(const Nan::FunctionCallbackInfo &info, const Tree *tree, TSNode node); Local GetMarshalNodes(const Nan::FunctionCallbackInfo &info, const Tree *tree, const TSNode *nodes, uint32_t node_count); -TSNode UnmarshalNode(const Tree *tree); +TSNode UnmarshalNode(AddonData* data, const Tree *tree); static inline const void *UnmarshalNodeId(const uint32_t *buffer) { const void *result; diff --git a/src/parser.cc b/src/parser.cc index 4eab1b5e..8507afb0 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -17,12 +17,11 @@ using namespace v8; using std::vector; using std::pair; -Nan::Persistent Parser::constructor; - class CallbackInput { public: - CallbackInput(v8::Local callback, v8::Local js_buffer_size) - : callback(callback), + CallbackInput(AddonData* data, v8::Local callback, v8::Local js_buffer_size) + : data(data), + callback(callback), byte_offset(0), partial_string_offset(0) { uint32_t buffer_size = Nan::To(js_buffer_size).FromMaybe(0); @@ -57,7 +56,7 @@ class CallbackInput { } else { Local callback = Nan::New(reader->callback); uint32_t utf16_unit = byte / 2; - Local argv[2] = { Nan::New(utf16_unit), PointToJS(position) }; + Local argv[2] = { Nan::New(utf16_unit), PointToJS(reader->data, position) }; TryCatch try_catch(Isolate::GetCurrent()); auto maybe_result_value = Nan::Call(callback, GetGlobal(callback), 2, argv); if (try_catch.HasCaught()) return nullptr; @@ -96,6 +95,7 @@ class CallbackInput { return (const char *)reader->buffer.data(); } + AddonData* data; Nan::Persistent callback; std::vector buffer; size_t byte_offset; @@ -103,8 +103,9 @@ class CallbackInput { size_t partial_string_offset; }; -void Parser::Init(Local exports) { - Local tpl = Nan::New(New); +void Parser::Init(Local exports, Local data_ext) { + AddonData* data = reinterpret_cast(data_ext->Value()); + Local tpl = Nan::New(New, data_ext); tpl->InstanceTemplate()->SetInternalFieldCount(1); Local class_name = Nan::New("Parser").ToLocalChecked(); tpl->SetClassName(class_name); @@ -118,11 +119,11 @@ void Parser::Init(Local exports) { }; for (size_t i = 0; i < length_of_array(methods); i++) { - Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback); + Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback, data_ext); } - constructor.Reset(Nan::Persistent(Nan::GetFunction(tpl).ToLocalChecked())); - Nan::Set(exports, class_name, Nan::New(constructor)); + data->parser_constructor.Reset(Nan::Persistent(Nan::GetFunction(tpl).ToLocalChecked())); + Nan::Set(exports, class_name, Nan::New(data->parser_constructor)); Nan::Set(exports, Nan::New("LANGUAGE_VERSION").ToLocalChecked(), Nan::New(TREE_SITTER_LANGUAGE_VERSION)); } @@ -130,7 +131,7 @@ Parser::Parser() : parser_(ts_parser_new()) {} Parser::~Parser() { ts_parser_delete(parser_); } -static bool handle_included_ranges(TSParser *parser, Local arg) { +static bool handle_included_ranges(AddonData* data, TSParser *parser, Local arg) { uint32_t last_included_range_end = 0; if (arg->IsArray()) { auto js_included_ranges = Local::Cast(arg); @@ -138,7 +139,7 @@ static bool handle_included_ranges(TSParser *parser, Local arg) { for (unsigned i = 0; i < js_included_ranges->Length(); i++) { Local range_value; if (!Nan::Get(js_included_ranges, i).ToLocal(&range_value)) return false; - auto maybe_range = RangeFromJS(range_value); + auto maybe_range = RangeFromJS(data, range_value); if (!maybe_range.IsJust()) return false; auto range = maybe_range.FromJust(); if (range.start_byte < last_included_range_end) { @@ -157,13 +158,14 @@ static bool handle_included_ranges(TSParser *parser, Local arg) { } void Parser::New(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); if (info.IsConstructCall()) { Parser *parser = new Parser(); parser->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } else { Local self; - MaybeLocal maybe_self = Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()); + MaybeLocal maybe_self = Nan::New(data->parser_constructor)->NewInstance(Nan::GetCurrentContext()); if (maybe_self.ToLocal(&self)) { info.GetReturnValue().Set(self); } else { @@ -183,6 +185,7 @@ void Parser::SetLanguage(const Nan::FunctionCallbackInfo &info) { } void Parser::Parse(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); Parser *parser = ObjectWrap::Unwrap(info.This()); if (!info[0]->IsFunction()) { @@ -195,7 +198,7 @@ void Parser::Parse(const Nan::FunctionCallbackInfo &info) { Local js_old_tree; const TSTree *old_tree = nullptr; if (info.Length() > 1 && !info[1]->IsNull() && !info[1]->IsUndefined() && Nan::To(info[1]).ToLocal(&js_old_tree)) { - const Tree *tree = Tree::UnwrapTree(js_old_tree); + const Tree *tree = Tree::UnwrapTree(data, js_old_tree); if (!tree) { Nan::ThrowTypeError("Second argument must be a tree"); return; @@ -206,11 +209,11 @@ void Parser::Parse(const Nan::FunctionCallbackInfo &info) { Local buffer_size = Nan::Null(); if (info.Length() > 2) buffer_size = info[2]; - if (!handle_included_ranges(parser->parser_, info[3])) return; + if (!handle_included_ranges(data, parser->parser_, info[3])) return; - CallbackInput callback_input(callback, buffer_size); + CallbackInput callback_input(data, callback, buffer_size); TSTree *tree = ts_parser_parse(parser->parser_, old_tree, callback_input.Input()); - Local result = Tree::NewInstance(tree); + Local result = Tree::NewInstance(data, tree); info.GetReturnValue().Set(result); } diff --git a/src/parser.h b/src/parser.h index 8fb893a0..07868c4b 100644 --- a/src/parser.h +++ b/src/parser.h @@ -10,7 +10,7 @@ namespace node_tree_sitter { class Parser : public Nan::ObjectWrap { public: - static void Init(v8::Local exports); + static void Init(v8::Local exports, v8::Local data_ext); TSParser *parser_; @@ -24,8 +24,6 @@ class Parser : public Nan::ObjectWrap { static void SetLogger(const Nan::FunctionCallbackInfo &); static void Parse(const Nan::FunctionCallbackInfo &); static void PrintDotGraphs(const Nan::FunctionCallbackInfo &); - - static Nan::Persistent constructor; }; } // namespace node_tree_sitter diff --git a/src/query.cc b/src/query.cc index 2c722b11..19f6c184 100644 --- a/src/query.cc +++ b/src/query.cc @@ -24,14 +24,11 @@ const char *query_error_names[] = { "TSQueryErrorStructure", }; -TSQueryCursor *Query::ts_query_cursor; -Nan::Persistent Query::constructor; -Nan::Persistent Query::constructor_template; +void Query::Init(Local exports, Local data_ext) { + AddonData* data = reinterpret_cast(data_ext->Value()); + data->ts_query_cursor = ts_query_cursor_new(); -void Query::Init(Local exports) { - ts_query_cursor = ts_query_cursor_new(); - - Local tpl = Nan::New(New); + Local tpl = Nan::New(New, data_ext); tpl->InstanceTemplate()->SetInternalFieldCount(1); Local class_name = Nan::New("Query").ToLocalChecked(); tpl->SetClassName(class_name); @@ -43,13 +40,13 @@ void Query::Init(Local exports) { }; for (size_t i = 0; i < length_of_array(methods); i++) { - Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback); + Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback, data_ext); } Local ctor = Nan::GetFunction(tpl).ToLocalChecked(); - constructor_template.Reset(tpl); - constructor.Reset(ctor); + data->query_constructor_template.Reset(tpl); + data->query_constructor.Reset(ctor); Nan::Set(exports, class_name, ctor); } @@ -59,10 +56,10 @@ Query::~Query() { ts_query_delete(query_); } -Local Query::NewInstance(TSQuery *query) { +Local Query::NewInstance(AddonData* data, TSQuery *query) { if (query) { Local self; - MaybeLocal maybe_self = Nan::NewInstance(Nan::New(constructor)); + MaybeLocal maybe_self = Nan::NewInstance(Nan::New(data->query_constructor)); if (maybe_self.ToLocal(&self)) { (new Query(query))->Wrap(self); return self; @@ -71,17 +68,18 @@ Local Query::NewInstance(TSQuery *query) { return Nan::Null(); } -Query *Query::UnwrapQuery(const Local &value) { +Query *Query::UnwrapQuery(AddonData* data, const Local &value) { if (!value->IsObject()) return nullptr; Local js_query = Local::Cast(value); - if (!Nan::New(constructor_template)->HasInstance(js_query)) return nullptr; + if (!Nan::New(data->query_constructor_template)->HasInstance(js_query)) return nullptr; return ObjectWrap::Unwrap(js_query); } void Query::New(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); if (!info.IsConstructCall()) { Local self; - MaybeLocal maybe_self = Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()); + MaybeLocal maybe_self = Nan::New(data->query_constructor)->NewInstance(Nan::GetCurrentContext()); if (maybe_self.ToLocal(&self)) { info.GetReturnValue().Set(self); } else { @@ -144,7 +142,8 @@ void Query::New(const Nan::FunctionCallbackInfo &info) { } void Query::GetPredicates(const Nan::FunctionCallbackInfo &info) { - Query *query = Query::UnwrapQuery(info.This()); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + Query *query = Query::UnwrapQuery(data, info.This()); auto ts_query = query->query_; auto pattern_len = ts_query_pattern_count(ts_query); @@ -197,8 +196,9 @@ void Query::GetPredicates(const Nan::FunctionCallbackInfo &info) { } void Query::Matches(const Nan::FunctionCallbackInfo &info) { - Query *query = Query::UnwrapQuery(info.This()); - const Tree *tree = Tree::UnwrapTree(info[0]); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + Query *query = Query::UnwrapQuery(data, info.This()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); uint32_t start_row = Nan::To(info[1]).ToChecked(); uint32_t start_column = Nan::To(info[2]).ToChecked() << 1; uint32_t end_row = Nan::To(info[3]).ToChecked(); @@ -215,18 +215,18 @@ void Query::Matches(const Nan::FunctionCallbackInfo &info) { } TSQuery *ts_query = query->query_; - TSNode rootNode = node_methods::UnmarshalNode(tree); + TSNode rootNode = node_methods::UnmarshalNode(data, tree); TSPoint start_point = {start_row, start_column}; TSPoint end_point = {end_row, end_column}; - ts_query_cursor_set_point_range(ts_query_cursor, start_point, end_point); - ts_query_cursor_exec(ts_query_cursor, ts_query, rootNode); + ts_query_cursor_set_point_range(data->ts_query_cursor, start_point, end_point); + ts_query_cursor_exec(data->ts_query_cursor, ts_query, rootNode); Local js_matches = Nan::New(); unsigned index = 0; vector nodes; TSQueryMatch match; - while (ts_query_cursor_next_match(ts_query_cursor, &match)) { + while (ts_query_cursor_next_match(data->ts_query_cursor, &match)) { Nan::Set(js_matches, index++, Nan::New(match.pattern_index)); for (uint16_t i = 0; i < match.capture_count; i++) { @@ -253,8 +253,9 @@ void Query::Matches(const Nan::FunctionCallbackInfo &info) { } void Query::Captures(const Nan::FunctionCallbackInfo &info) { - Query *query = Query::UnwrapQuery(info.This()); - const Tree *tree = Tree::UnwrapTree(info[0]); + AddonData* data = reinterpret_cast(info.Data().As()->Value()); + Query *query = Query::UnwrapQuery(data, info.This()); + const Tree *tree = Tree::UnwrapTree(data, info[0]); uint32_t start_row = Nan::To(info[1]).ToChecked(); uint32_t start_column = Nan::To(info[2]).ToChecked() << 1; uint32_t end_row = Nan::To(info[3]).ToChecked(); @@ -271,11 +272,11 @@ void Query::Captures(const Nan::FunctionCallbackInfo &info) { } TSQuery *ts_query = query->query_; - TSNode rootNode = node_methods::UnmarshalNode(tree); + TSNode rootNode = node_methods::UnmarshalNode(data, tree); TSPoint start_point = {start_row, start_column}; TSPoint end_point = {end_row, end_column}; - ts_query_cursor_set_point_range(ts_query_cursor, start_point, end_point); - ts_query_cursor_exec(ts_query_cursor, ts_query, rootNode); + ts_query_cursor_set_point_range(data->ts_query_cursor, start_point, end_point); + ts_query_cursor_exec(data->ts_query_cursor, ts_query, rootNode); Local js_matches = Nan::New(); unsigned index = 0; @@ -284,7 +285,7 @@ void Query::Captures(const Nan::FunctionCallbackInfo &info) { uint32_t capture_index; while (ts_query_cursor_next_capture( - ts_query_cursor, + data->ts_query_cursor, &match, &capture_index )) { diff --git a/src/query.h b/src/query.h index 955e621f..5b48a931 100644 --- a/src/query.h +++ b/src/query.h @@ -6,14 +6,15 @@ #include #include #include +#include "./addon_data.h" namespace node_tree_sitter { class Query : public Nan::ObjectWrap { public: - static void Init(v8::Local exports); - static v8::Local NewInstance(TSQuery *); - static Query *UnwrapQuery(const v8::Local &); + static void Init(v8::Local exports, v8::Local data_ext); + static v8::Local NewInstance(AddonData* data, TSQuery *); + static Query *UnwrapQuery(AddonData* data, const v8::Local &); TSQuery *query_; @@ -25,10 +26,6 @@ class Query : public Nan::ObjectWrap { static void Matches(const Nan::FunctionCallbackInfo &); static void Captures(const Nan::FunctionCallbackInfo &); static void GetPredicates(const Nan::FunctionCallbackInfo &); - - static TSQueryCursor *ts_query_cursor; - static Nan::Persistent constructor; - static Nan::Persistent constructor_template; }; } // namespace node_tree_sitter diff --git a/src/tree.cc b/src/tree.cc index bfe8d248..0ad0cd1f 100644 --- a/src/tree.cc +++ b/src/tree.cc @@ -1,4 +1,5 @@ #include "./tree.h" +#include "./addon_data.h" #include #include #include @@ -12,11 +13,9 @@ namespace node_tree_sitter { using namespace v8; using node_methods::UnmarshalNodeId; -Nan::Persistent Tree::constructor; -Nan::Persistent Tree::constructor_template; - -void Tree::Init(Local exports) { - Local tpl = Nan::New(New); +void Tree::Init(Local exports, Local data_ext) { + AddonData* data = reinterpret_cast(data_ext->Value()); + Local tpl = Nan::New(New, data_ext); tpl->InstanceTemplate()->SetInternalFieldCount(1); Local class_name = Nan::New("Tree").ToLocalChecked(); tpl->SetClassName(class_name); @@ -32,13 +31,13 @@ void Tree::Init(Local exports) { }; for (size_t i = 0; i < length_of_array(methods); i++) { - Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback); + Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback, data_ext); } Local ctor = Nan::GetFunction(tpl).ToLocalChecked(); - constructor_template.Reset(tpl); - constructor.Reset(ctor); + data->tree_constructor_template.Reset(tpl); + data->tree_constructor.Reset(ctor); Nan::Set(exports, class_name, ctor); } @@ -51,10 +50,10 @@ Tree::~Tree() { } } -Local Tree::NewInstance(TSTree *tree) { +Local Tree::NewInstance(AddonData* data, TSTree *tree) { if (tree) { Local self; - MaybeLocal maybe_self = Nan::NewInstance(Nan::New(constructor)); + MaybeLocal maybe_self = Nan::NewInstance(Nan::New(data->tree_constructor)); if (maybe_self.ToLocal(&self)) { (new Tree(tree))->Wrap(self); return self; @@ -63,10 +62,10 @@ Local Tree::NewInstance(TSTree *tree) { return Nan::Null(); } -const Tree *Tree::UnwrapTree(const Local &value) { +const Tree *Tree::UnwrapTree(AddonData* data, const Local &value) { if (!value->IsObject()) return nullptr; Local js_tree = Local::Cast(value); - if (!Nan::New(constructor_template)->HasInstance(js_tree)) return nullptr; + if (!Nan::New(data->tree_constructor_template)->HasInstance(js_tree)) return nullptr; return ObjectWrap::Unwrap(js_tree); } @@ -128,8 +127,9 @@ void Tree::RootNode(const Nan::FunctionCallbackInfo &info) { } void Tree::GetChangedRanges(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); const Tree *tree = ObjectWrap::Unwrap(info.This()); - const Tree *other_tree = UnwrapTree(info[0]); + const Tree *other_tree = UnwrapTree(data, info[0]); if (!other_tree) { Nan::ThrowTypeError("Argument must be a tree"); return; @@ -140,7 +140,7 @@ void Tree::GetChangedRanges(const Nan::FunctionCallbackInfo &info) { Local result = Nan::New(); for (size_t i = 0; i < range_count; i++) { - Nan::Set(result, i, RangeToJS(ranges[i])); + Nan::Set(result, i, RangeToJS(data, ranges[i])); } free(ranges); @@ -149,6 +149,7 @@ void Tree::GetChangedRanges(const Nan::FunctionCallbackInfo &info) { } void Tree::GetEditedRange(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); Tree *tree = ObjectWrap::Unwrap(info.This()); TSNode root = ts_tree_root_node(tree->tree_); if (!ts_node_has_changes(root)) return; @@ -193,7 +194,7 @@ void Tree::GetEditedRange(const Nan::FunctionCallbackInfo &info) { } ts_tree_cursor_delete(&cursor); - info.GetReturnValue().Set(RangeToJS(result)); + info.GetReturnValue().Set(RangeToJS(data, result)); } void Tree::PrintDotGraph(const Nan::FunctionCallbackInfo &info) { diff --git a/src/tree.h b/src/tree.h index 5ed4e316..6a1340b2 100644 --- a/src/tree.h +++ b/src/tree.h @@ -6,14 +6,15 @@ #include #include #include +#include "./addon_data.h" namespace node_tree_sitter { class Tree : public Nan::ObjectWrap { public: - static void Init(v8::Local exports); - static v8::Local NewInstance(TSTree *); - static const Tree *UnwrapTree(const v8::Local &); + static void Init(v8::Local exports, v8::Local data_ext); + static v8::Local NewInstance(AddonData* data, TSTree *); + static const Tree *UnwrapTree(AddonData* data, const v8::Local &); struct NodeCacheEntry { Tree *tree; @@ -37,8 +38,6 @@ class Tree : public Nan::ObjectWrap { static void CacheNode(const Nan::FunctionCallbackInfo &); static void CacheNodes(const Nan::FunctionCallbackInfo &); - static Nan::Persistent constructor; - static Nan::Persistent constructor_template; }; } // namespace node_tree_sitter diff --git a/src/tree_cursor.cc b/src/tree_cursor.cc index adcadf67..66a55f09 100644 --- a/src/tree_cursor.cc +++ b/src/tree_cursor.cc @@ -11,10 +11,9 @@ namespace node_tree_sitter { using namespace v8; -Nan::Persistent TreeCursor::constructor; - -void TreeCursor::Init(v8::Local exports) { - Local tpl = Nan::New(New); +void TreeCursor::Init(v8::Local exports, v8::Local data_ext) { + AddonData* data = reinterpret_cast(data_ext->Value()); + Local tpl = Nan::New(New, data_ext); Local class_name = Nan::New("TreeCursor").ToLocalChecked(); tpl->SetClassName(class_name); tpl->InstanceTemplate()->SetInternalFieldCount(1); @@ -47,17 +46,17 @@ void TreeCursor::Init(v8::Local exports) { } for (size_t i = 0; i < length_of_array(methods); i++) { - Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback); + Nan::SetPrototypeMethod(tpl, methods[i].name, methods[i].callback, data_ext); } Local constructor_local = Nan::GetFunction(tpl).ToLocalChecked(); Nan::Set(exports, class_name, constructor_local); - constructor.Reset(Nan::Persistent(constructor_local)); + data->tree_cursor_constructor.Reset(Nan::Persistent(constructor_local)); } -Local TreeCursor::NewInstance(TSTreeCursor cursor) { +Local TreeCursor::NewInstance(AddonData* data, TSTreeCursor cursor) { Local self; - MaybeLocal maybe_self = Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()); + MaybeLocal maybe_self = Nan::New(data->tree_cursor_constructor)->NewInstance(Nan::GetCurrentContext()); if (maybe_self.ToLocal(&self)) { (new TreeCursor(cursor))->Wrap(self); return self; @@ -109,30 +108,34 @@ void TreeCursor::GotoNextSibling(const Nan::FunctionCallbackInfo &info) { } void TreeCursor::StartPosition(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); TreeCursor *cursor = Nan::ObjectWrap::Unwrap(info.This()); TSNode node = ts_tree_cursor_current_node(&cursor->cursor_); - TransferPoint(ts_node_start_point(node)); + TransferPoint(data, ts_node_start_point(node)); } void TreeCursor::EndPosition(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); TreeCursor *cursor = Nan::ObjectWrap::Unwrap(info.This()); TSNode node = ts_tree_cursor_current_node(&cursor->cursor_); - TransferPoint(ts_node_end_point(node)); + TransferPoint(data, ts_node_end_point(node)); } void TreeCursor::CurrentNode(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); TreeCursor *cursor = Nan::ObjectWrap::Unwrap(info.This()); Local key = Nan::New("tree").ToLocalChecked(); - const Tree *tree = Tree::UnwrapTree(Nan::Get(info.This(), key).ToLocalChecked()); + const Tree *tree = Tree::UnwrapTree(data, Nan::Get(info.This(), key).ToLocalChecked()); TSNode node = ts_tree_cursor_current_node(&cursor->cursor_); node_methods::MarshalNode(info, tree, node); } void TreeCursor::Reset(const Nan::FunctionCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); TreeCursor *cursor = Nan::ObjectWrap::Unwrap(info.This()); Local key = Nan::New("tree").ToLocalChecked(); - const Tree *tree = Tree::UnwrapTree(Nan::Get(info.This(), key).ToLocalChecked()); - TSNode node = node_methods::UnmarshalNode(tree); + const Tree *tree = Tree::UnwrapTree(data, Nan::Get(info.This(), key).ToLocalChecked()); + TSNode node = node_methods::UnmarshalNode(data, tree); ts_tree_cursor_reset(&cursor->cursor_, node); } @@ -165,15 +168,17 @@ void TreeCursor::CurrentFieldName(v8::Local prop, const Nan::Propert } void TreeCursor::StartIndex(v8::Local prop, const Nan::PropertyCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); TreeCursor *cursor = Nan::ObjectWrap::Unwrap(info.This()); TSNode node = ts_tree_cursor_current_node(&cursor->cursor_); - info.GetReturnValue().Set(ByteCountToJS(ts_node_start_byte(node))); + info.GetReturnValue().Set(ByteCountToJS(data, ts_node_start_byte(node))); } void TreeCursor::EndIndex(v8::Local prop, const Nan::PropertyCallbackInfo &info) { + AddonData* data = reinterpret_cast(info.Data().As()->Value()); TreeCursor *cursor = Nan::ObjectWrap::Unwrap(info.This()); TSNode node = ts_tree_cursor_current_node(&cursor->cursor_); - info.GetReturnValue().Set(ByteCountToJS(ts_node_end_byte(node))); + info.GetReturnValue().Set(ByteCountToJS(data, ts_node_end_byte(node))); } } diff --git a/src/tree_cursor.h b/src/tree_cursor.h index e02f5a6a..1f70a151 100644 --- a/src/tree_cursor.h +++ b/src/tree_cursor.h @@ -5,13 +5,14 @@ #include #include #include +#include "./addon_data.h" namespace node_tree_sitter { class TreeCursor : public Nan::ObjectWrap { public: - static void Init(v8::Local exports); - static v8::Local NewInstance(TSTreeCursor); + static void Init(v8::Local exports, v8::Local data_ext); + static v8::Local NewInstance(AddonData* data, TSTreeCursor); private: explicit TreeCursor(TSTreeCursor); @@ -35,8 +36,6 @@ class TreeCursor : public Nan::ObjectWrap { static void EndIndex(v8::Local, const Nan::PropertyCallbackInfo &); TSTreeCursor cursor_; - static Nan::Persistent constructor; - static Nan::Persistent constructor_template; }; } // namespace node_tree_sitter