@openzim/libzim 3.4.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,167 @@
1
+ #pragma once
2
+
3
+ #include <napi.h>
4
+ #include <zim/illustration.h>
5
+
6
+ #include <exception>
7
+ #include <map>
8
+ #include <string>
9
+
10
+ class IllustrationInfo : public Napi::ObjectWrap<IllustrationInfo> {
11
+ public:
12
+ explicit IllustrationInfo(const Napi::CallbackInfo &info)
13
+ : Napi::ObjectWrap<IllustrationInfo>(info), ii_{} {
14
+ Napi::Env env = info.Env();
15
+
16
+ if (info.Length() == 0) {
17
+ // Default constructor
18
+ ii_ = zim::IllustrationInfo{};
19
+ return;
20
+ }
21
+
22
+ // IllustrationInfo(ii: External<zim::IllustrationInfo>)
23
+ // Construct from external, used internally
24
+ if (info[0].IsExternal()) {
25
+ auto ext = info[0].As<Napi::External<zim::IllustrationInfo>>();
26
+ ii_ = *(ext.Data());
27
+ return;
28
+ }
29
+
30
+ if (!info[0].IsObject()) {
31
+ throw Napi::Error::New(env,
32
+ "IllustrationInfo constructor expects an "
33
+ "IllustrationInfo like object");
34
+ }
35
+
36
+ auto value = info[0];
37
+ // IllustrationInfo(ii: IllustrationInfo)
38
+ // Copy constructor
39
+ if (InstanceOf(env, value)) {
40
+ auto unwrapped = Unwrap(value.As<Napi::Object>());
41
+ ii_ = zim::IllustrationInfo(unwrapped->ii_);
42
+ return;
43
+ }
44
+
45
+ // IllustrationInfo(ii: object)
46
+ // Construct from object
47
+ ii_ = infoFrom(value.As<Napi::Object>());
48
+ }
49
+
50
+ static Napi::Object New(Napi::Env env, const zim::IllustrationInfo &ii) {
51
+ Napi::FunctionReference &constructor = GetConstructor(env);
52
+ auto data = Napi::External<zim::IllustrationInfo>::New(
53
+ env, new zim::IllustrationInfo(ii),
54
+ [](Napi::BasicEnv /*env*/, zim::IllustrationInfo *ptr) { delete ptr; });
55
+ return constructor.New({data});
56
+ }
57
+
58
+ /**
59
+ * Construct zim::IllustrationInfo from a JS object
60
+ */
61
+ static zim::IllustrationInfo infoFrom(Napi::Object obj) {
62
+ zim::IllustrationInfo ii{
63
+ .width =
64
+ obj.Has("width") ? obj.Get("width").ToNumber().Uint32Value() : 0,
65
+ .height =
66
+ obj.Has("height") ? obj.Get("height").ToNumber().Uint32Value() : 0,
67
+ .scale =
68
+ obj.Has("scale") ? obj.Get("scale").ToNumber().FloatValue() : 0.0f,
69
+ .extraAttributes = std::map<std::string, std::string>{},
70
+ };
71
+
72
+ if (obj.Has("extraAttributes") && obj.Get("extraAttributes").IsObject()) {
73
+ auto extraAttributes = obj.Get("extraAttributes").ToObject();
74
+ auto keys = extraAttributes.GetPropertyNames();
75
+ for (const auto &e : keys) {
76
+ auto key =
77
+ static_cast<Napi::Value>(e.second).As<Napi::String>().Utf8Value();
78
+ auto value = extraAttributes.Get(key).ToString().Utf8Value();
79
+ ii.extraAttributes[key] = value;
80
+ }
81
+ }
82
+
83
+ return ii;
84
+ }
85
+
86
+ Napi::Value getWidth(const Napi::CallbackInfo &info) {
87
+ Napi::Env env = info.Env();
88
+ return Napi::Value::From(env, ii_.width);
89
+ }
90
+
91
+ Napi::Value getHeight(const Napi::CallbackInfo &info) {
92
+ Napi::Env env = info.Env();
93
+ return Napi::Value::From(env, ii_.height);
94
+ }
95
+
96
+ Napi::Value getScale(const Napi::CallbackInfo &info) {
97
+ Napi::Env env = info.Env();
98
+ return Napi::Value::From(env, ii_.scale);
99
+ }
100
+
101
+ Napi::Value getExtraAttributes(const Napi::CallbackInfo &info) {
102
+ Napi::Env env = info.Env();
103
+ Napi::Object obj = Napi::Object::New(env);
104
+ for (const auto &pair : ii_.extraAttributes) {
105
+ obj.Set(pair.first, pair.second);
106
+ }
107
+ obj.Freeze();
108
+ return obj;
109
+ }
110
+
111
+ Napi::Value asMetadataItemName(const Napi::CallbackInfo &info) {
112
+ Napi::Env env = info.Env();
113
+ return Napi::Value::From(env, ii_.asMetadataItemName());
114
+ }
115
+
116
+ static Napi::Value fromMetadataItemName(const Napi::CallbackInfo &info) {
117
+ Napi::Env env = info.Env();
118
+ if (info.Length() < 1 || !info[0].IsString()) {
119
+ throw Napi::TypeError::New(
120
+ env, "First argument must be a string for metadata item name.");
121
+ }
122
+
123
+ auto name = info[0].As<Napi::String>().Utf8Value();
124
+ auto ii = zim::IllustrationInfo::fromMetadataItemName(name);
125
+ return New(env, ii);
126
+ }
127
+
128
+ static bool InstanceOf(Napi::Env env, Napi::Value value) {
129
+ if (!value.IsObject()) {
130
+ return false;
131
+ }
132
+ Napi::Object obj = value.As<Napi::Object>();
133
+ Napi::FunctionReference &constructor = GetConstructor(env);
134
+ return obj.InstanceOf(constructor.Value());
135
+ }
136
+
137
+ static Napi::FunctionReference &GetConstructor(Napi::Env env) {
138
+ auto constructors = env.GetInstanceData<ModuleConstructors>();
139
+ return constructors->illustrationInfo;
140
+ }
141
+
142
+ zim::IllustrationInfo &getInternalIllustrationInfo() { return ii_; }
143
+
144
+ static void Init(Napi::Env env, Napi::Object exports,
145
+ ModuleConstructors &constructors) {
146
+ Napi::Function func = DefineClass(
147
+ env, "IllustrationInfo",
148
+ {
149
+ InstanceAccessor<&IllustrationInfo::getWidth>("width"),
150
+ InstanceAccessor<&IllustrationInfo::getHeight>("height"),
151
+ InstanceAccessor<&IllustrationInfo::getScale>("scale"),
152
+ InstanceAccessor<&IllustrationInfo::getExtraAttributes>(
153
+ "extraAttributes"),
154
+ InstanceMethod<&IllustrationInfo::asMetadataItemName>(
155
+ "asMetadataItemName"),
156
+ StaticMethod<&IllustrationInfo::fromMetadataItemName>(
157
+ "fromMetadataItemName"),
158
+ });
159
+
160
+ exports.Set("IllustrationInfo", func);
161
+ constructors.illustrationInfo = Napi::Persistent(func);
162
+ }
163
+
164
+ private:
165
+ zim::IllustrationInfo ii_;
166
+ };
167
+
package/src/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ export declare function getClusterCacheMaxSize(): number;
2
+ export declare function getClusterCacheCurrentSize(): number;
3
+ export declare function setClusterCacheMaxSize(nbClusters: number): void;
4
+
1
5
  export class IntegrityCheck {
2
6
  static CHECKSUM: symbol;
3
7
  static DIRENT_PTRS: symbol;
@@ -104,7 +108,10 @@ export class Creator {
104
108
  content: string | ContentProvider,
105
109
  mimetype?: string,
106
110
  ): void;
107
- addIllustration(size: number, content: string | ContentProvider): void;
111
+ addIllustration(
112
+ sizeOrInfo: number | IIllustrationInfo,
113
+ content: string | ContentProvider,
114
+ ): void;
108
115
  addRedirection(
109
116
  path: string,
110
117
  title: string,
@@ -146,8 +153,35 @@ export interface EntryRange extends Iterable<Entry> {
146
153
  offset(start: number, maxResults: number): EntryRange;
147
154
  }
148
155
 
156
+ export interface IIllustrationInfo {
157
+ width?: number;
158
+ height?: number;
159
+ scale?: number;
160
+ extraAttributes?: Record<string, string>;
161
+ }
162
+
163
+ export class IllustrationInfo implements IIllustrationInfo {
164
+ constructor(info?: IIllustrationInfo | IllustrationInfo);
165
+ get width(): number;
166
+ get height(): number;
167
+ get scale(): number;
168
+ get extraAttributes(): Record<string, string>;
169
+ asMetadataItemName(): string;
170
+ static fromMetadataItemName(name: string): IllustrationInfo;
171
+ }
172
+
173
+ export class OpenConfig {
174
+ constructor();
175
+
176
+ preloadXapianDb(preload: boolean): this;
177
+ preloadDirentRanges(nbRanges: number): this;
178
+
179
+ get m_preloadXapianDb(): boolean;
180
+ get m_preloadDirentRanges(): number;
181
+ }
182
+
149
183
  export class Archive {
150
- constructor(filepath: string);
184
+ constructor(filepath: string, config?: OpenConfig);
151
185
  get filename(): string;
152
186
  get filesize(): number | bigint;
153
187
  get allEntryCount(): number;
@@ -158,8 +192,14 @@ export class Archive {
158
192
  getMetadata(name: string): string;
159
193
  getMetadataItem(name: string): Item;
160
194
  get metadataKeys(): string[];
161
- getIllustrationItem(size: number): Item;
195
+ getIllustrationItem(sizeOrInfo?: number | IIllustrationInfo): Item;
162
196
  get illustrationSizes(): Set<number>;
197
+ getIllustrationInfos(
198
+ width?: number,
199
+ height?: number,
200
+ minScale?: number,
201
+ ): IllustrationInfo[];
202
+ get illustrationInfos(): IllustrationInfo[];
163
203
  getEntryByPath(path_or_idx: string | number): Entry;
164
204
  getEntryByTitle(title_or_idx: string | number): Entry;
165
205
  getEntryByClusterOrder(idx: number): Entry;
@@ -182,14 +222,9 @@ export class Archive {
182
222
  checkIntegrity(checkType: symbol): boolean; // one of IntegrityCheck
183
223
  get isMultiPart(): boolean;
184
224
  get hasNewNamespaceScheme(): boolean;
185
- getClusterCacheMaxSize(): number;
186
- getClusterCacheCurrentSize(): number;
187
- setClusterCacheMaxSize(nbClusters: number): void;
188
225
  getDirentCacheMaxSize(): number;
189
226
  getDirentCacheCurrentSize(): number;
190
227
  setDirentCacheMaxSize(nbDirents: number): void;
191
- getDirentLookupCacheMaxSize(): number;
192
- setDirentLookupCacheMaxSize(nbRanges: number): void;
193
228
 
194
229
  static validate(zimPath: string, checksToRun: symbol[]): boolean; // list of IntegrityCheck
195
230
  }
package/src/index.js CHANGED
@@ -2,9 +2,11 @@ import bindings from "bindings";
2
2
 
3
3
  export const {
4
4
  Archive,
5
+ OpenConfig,
5
6
  Entry,
6
7
  IntegrityCheck,
7
8
  Compression,
9
+ IllustrationInfo,
8
10
  Blob,
9
11
  Searcher,
10
12
  Query,
@@ -14,4 +16,7 @@ export const {
14
16
  FileProvider,
15
17
  StringItem,
16
18
  FileItem,
19
+ getClusterCacheMaxSize,
20
+ getClusterCacheCurrentSize,
21
+ setClusterCacheMaxSize,
17
22
  } = bindings("zim_binding");
package/src/item.h CHANGED
@@ -12,7 +12,6 @@ class Item : public Napi::ObjectWrap<Item> {
12
12
  explicit Item(const Napi::CallbackInfo &info)
13
13
  : Napi::ObjectWrap<Item>(info), item_{nullptr} {
14
14
  Napi::Env env = info.Env();
15
- Napi::HandleScope scope(env);
16
15
 
17
16
  if (!info[0].IsExternal()) {
18
17
  throw Napi::Error::New(
@@ -108,10 +107,12 @@ class Item : public Napi::ObjectWrap<Item> {
108
107
  Napi::Value getDirectAccessInformation(const Napi::CallbackInfo &info) {
109
108
  try {
110
109
  auto env = info.Env();
111
- const auto valPair = item_->getDirectAccessInformation();
110
+ const auto dai = item_->getDirectAccessInformation();
112
111
  auto res = Napi::Object::New(env);
113
- res["filename"] = Napi::Value::From(env, valPair.first);
114
- res["offset"] = Napi::Value::From(env, valPair.second);
112
+ res["filename"] = Napi::Value::From(env, dai.filename);
113
+ res["offset"] = Napi::Value::From(env, dai.offset);
114
+ res["isValid"] = Napi::Value::From(env, dai.isValid());
115
+ res.Freeze();
115
116
  return res;
116
117
  } catch (const std::exception &err) {
117
118
  throw Napi::Error::New(info.Env(), err.what());
@@ -128,7 +129,6 @@ class Item : public Napi::ObjectWrap<Item> {
128
129
 
129
130
  static void Init(Napi::Env env, Napi::Object exports,
130
131
  ModuleConstructors &constructors) {
131
- Napi::HandleScope scope(env);
132
132
  Napi::Function func =
133
133
  DefineClass(env, "Item",
134
134
  {
package/src/module.cc CHANGED
@@ -7,7 +7,9 @@
7
7
  #include "contentProvider.h"
8
8
  #include "creator.h"
9
9
  #include "entry.h"
10
+ #include "illustration.h"
10
11
  #include "item.h"
12
+ #include "openconfig.h"
11
13
  #include "search.h"
12
14
  #include "suggestion.h"
13
15
  #include "writerItem.h"
@@ -26,6 +28,8 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
26
28
  Item::Init(env, exports, *constructors);
27
29
  Entry::Init(env, exports, *constructors);
28
30
  Archive::Init(env, exports, *constructors);
31
+ OpenConfig::Init(env, exports, *constructors);
32
+ IllustrationInfo::Init(env, exports, *constructors);
29
33
 
30
34
  Searcher::Init(env, exports, *constructors);
31
35
  Query::Init(env, exports, *constructors);
@@ -45,6 +49,28 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
45
49
  StringItem::Init(env, exports, *constructors);
46
50
  FileItem::Init(env, exports, *constructors);
47
51
 
52
+ // Extra helper functions from libzim
53
+ exports.Set("getClusterCacheMaxSize",
54
+ Napi::Function::New(env, [](const Napi::CallbackInfo &info) {
55
+ return Napi::Value::From(info.Env(),
56
+ zim::getClusterCacheMaxSize());
57
+ }));
58
+ exports.Set("getClusterCacheCurrentSize",
59
+ Napi::Function::New(env, [](const Napi::CallbackInfo &info) {
60
+ return Napi::Value::From(info.Env(),
61
+ zim::getClusterCacheCurrentSize());
62
+ }));
63
+ exports.Set("setClusterCacheMaxSize",
64
+ Napi::Function::New(env, [](const Napi::CallbackInfo &info) {
65
+ if (info.Length() < 1 || !info[0].IsNumber()) {
66
+ throw Napi::TypeError::New(
67
+ info.Env(),
68
+ "First argument must be a number for max size.");
69
+ }
70
+ auto size = info[0].As<Napi::Number>().Int64Value();
71
+ zim::setClusterCacheMaxSize(size);
72
+ }));
73
+
48
74
  return exports;
49
75
  }
50
76
 
@@ -0,0 +1,83 @@
1
+ #pragma once
2
+
3
+ #include <napi.h>
4
+ #include <zim/zim.h>
5
+
6
+ class OpenConfig : public Napi::ObjectWrap<OpenConfig> {
7
+ public:
8
+ explicit OpenConfig(const Napi::CallbackInfo& info)
9
+ : Napi::ObjectWrap<OpenConfig>(info), config_{zim::OpenConfig()} {
10
+ if (info.Length() > 0) {
11
+ throw Napi::Error::New(
12
+ info.Env(), "OpenConfig constructor does not take any arguments.");
13
+ }
14
+ }
15
+
16
+ Napi::Value preloadXapianDb(const Napi::CallbackInfo& info) {
17
+ Napi::Env env = info.Env();
18
+ if (info.Length() < 1 || !info[0].IsBoolean()) {
19
+ throw Napi::TypeError::New(
20
+ env, "First argument must be a boolean for preloadXapianDb.");
21
+ }
22
+ bool value = info[0].As<Napi::Boolean>().Value();
23
+ config_.preloadXapianDb(value);
24
+ return info.This();
25
+ }
26
+
27
+ Napi::Value preloadDirentRanges(const Napi::CallbackInfo& info) {
28
+ Napi::Env env = info.Env();
29
+ if (info.Length() < 1 || !info[0].IsNumber()) {
30
+ throw Napi::TypeError::New(
31
+ env, "First argument must be a number for preloadDirentRanges.");
32
+ }
33
+ int value = info[0].As<Napi::Number>().Int32Value();
34
+ config_.preloadDirentRanges(value);
35
+ return info.This();
36
+ }
37
+
38
+ Napi::Value getPreloadXapianDb(const Napi::CallbackInfo& info) {
39
+ Napi::Env env = info.Env();
40
+ return Napi::Value::From(env, config_.m_preloadXapianDb);
41
+ }
42
+
43
+ Napi::Value getPreloadDirentRanges(const Napi::CallbackInfo& info) {
44
+ Napi::Env env = info.Env();
45
+ return Napi::Value::From(env, config_.m_preloadDirentRanges);
46
+ }
47
+
48
+ static Napi::FunctionReference& GetConstructor(Napi::Env env) {
49
+ return env.GetInstanceData<ModuleConstructors>()->openConfig;
50
+ }
51
+
52
+ static bool InstanceOf(Napi::Env env, Napi::Value value) {
53
+ if (!value.IsObject()) {
54
+ return false;
55
+ }
56
+ Napi::Object obj = value.As<Napi::Object>();
57
+ Napi::FunctionReference& constructor = GetConstructor(env);
58
+ return obj.InstanceOf(constructor.Value());
59
+ }
60
+
61
+ const zim::OpenConfig& getInternalConfig() const { return config_; }
62
+
63
+ static void Init(Napi::Env env, Napi::Object exports,
64
+ ModuleConstructors& constructors) {
65
+ Napi::Function func = DefineClass(
66
+ env, "OpenConfig",
67
+ {
68
+ InstanceMethod<&OpenConfig::preloadXapianDb>("preloadXapianDb"),
69
+ InstanceMethod<&OpenConfig::preloadDirentRanges>(
70
+ "preloadDirentRanges"),
71
+ InstanceAccessor<&OpenConfig::getPreloadXapianDb>(
72
+ "m_preloadXapianDb"),
73
+ InstanceAccessor<&OpenConfig::getPreloadDirentRanges>(
74
+ "m_preloadDirentRanges"),
75
+ });
76
+
77
+ exports.Set("OpenConfig", func);
78
+ constructors.openConfig = Napi::Persistent(func);
79
+ }
80
+
81
+ private:
82
+ zim::OpenConfig config_;
83
+ };
package/src/search.h CHANGED
@@ -118,7 +118,6 @@ class Query : public Napi::ObjectWrap<Query> {
118
118
 
119
119
  static void Init(Napi::Env env, Napi::Object exports,
120
120
  ModuleConstructors &constructors) {
121
- Napi::HandleScope scope(env);
122
121
  Napi::Function func = DefineClass(
123
122
  env, "Query",
124
123
  {
@@ -144,9 +143,6 @@ class SearchIterator : public Napi::ObjectWrap<SearchIterator> {
144
143
  public:
145
144
  explicit SearchIterator(const Napi::CallbackInfo &info)
146
145
  : Napi::ObjectWrap<SearchIterator>(info), searchIterator_{} {
147
- Napi::Env env = info.Env();
148
- Napi::HandleScope scope(env);
149
-
150
146
  if (info[0].IsExternal()) {
151
147
  searchIterator_ =
152
148
  *info[0].As<Napi::External<zim::SearchIterator>>().Data();
@@ -233,7 +229,6 @@ class SearchIterator : public Napi::ObjectWrap<SearchIterator> {
233
229
 
234
230
  static void Init(Napi::Env env, Napi::Object exports,
235
231
  ModuleConstructors &constructors) {
236
- Napi::HandleScope scope(env);
237
232
  Napi::Function func = DefineClass(
238
233
  env, "SearchIterator",
239
234
  {
@@ -260,7 +255,6 @@ class SearchResultSet : public Napi::ObjectWrap<SearchResultSet> {
260
255
  explicit SearchResultSet(const Napi::CallbackInfo &info)
261
256
  : Napi::ObjectWrap<SearchResultSet>(info), searchResultSet_{nullptr} {
262
257
  Napi::Env env = info.Env();
263
- Napi::HandleScope scope(env);
264
258
 
265
259
  if (!info[0].IsExternal()) {
266
260
  throw Napi::Error::New(env,
@@ -326,7 +320,6 @@ class SearchResultSet : public Napi::ObjectWrap<SearchResultSet> {
326
320
 
327
321
  static void Init(Napi::Env env, Napi::Object exports,
328
322
  ModuleConstructors &constructors) {
329
- Napi::HandleScope scope(env);
330
323
  Napi::Function func =
331
324
  DefineClass(env, "SearchResultSet",
332
325
  {
@@ -347,11 +340,8 @@ class Search : public Napi::ObjectWrap<Search> {
347
340
  public:
348
341
  explicit Search(const Napi::CallbackInfo &info)
349
342
  : Napi::ObjectWrap<Search>(info), search_{nullptr} {
350
- Napi::Env env = info.Env();
351
- Napi::HandleScope scope(env);
352
-
353
343
  if (!info[0].IsExternal()) {
354
- throw Napi::Error::New(env, "Search must be created internally.");
344
+ throw Napi::Error::New(info.Env(), "Search must be created internally.");
355
345
  }
356
346
 
357
347
  search_ = std::make_shared<zim::Search>(
@@ -393,7 +383,6 @@ class Search : public Napi::ObjectWrap<Search> {
393
383
 
394
384
  static void Init(Napi::Env env, Napi::Object exports,
395
385
  ModuleConstructors &constructors) {
396
- Napi::HandleScope scope(env);
397
386
  Napi::Function func = DefineClass(
398
387
  env, "Search",
399
388
  {
@@ -414,7 +403,6 @@ class Searcher : public Napi::ObjectWrap<Searcher> {
414
403
  explicit Searcher(const Napi::CallbackInfo &info)
415
404
  : Napi::ObjectWrap<Searcher>(info), searcher_{nullptr} {
416
405
  Napi::Env env = info.Env();
417
- Napi::HandleScope scope(env);
418
406
 
419
407
  if (info[0].IsArray()) {
420
408
  auto array = info[0].As<Napi::Array>();
@@ -499,7 +487,6 @@ class Searcher : public Napi::ObjectWrap<Searcher> {
499
487
 
500
488
  static void Init(Napi::Env env, Napi::Object exports,
501
489
  ModuleConstructors &constructors) {
502
- Napi::HandleScope scope(env);
503
490
  Napi::Function func =
504
491
  DefineClass(env, "Searcher",
505
492
  {
package/src/suggestion.h CHANGED
@@ -17,9 +17,6 @@ class SuggestionIterator : public Napi::ObjectWrap<SuggestionIterator> {
17
17
  public:
18
18
  explicit SuggestionIterator(const Napi::CallbackInfo &info)
19
19
  : Napi::ObjectWrap<SuggestionIterator>(info), iterator_{} {
20
- Napi::Env env = info.Env();
21
- Napi::HandleScope scope(env);
22
-
23
20
  if (info[0].IsExternal()) {
24
21
  iterator_ = *info[0].As<Napi::External<decltype(iterator_)>>().Data();
25
22
  }
@@ -75,7 +72,6 @@ class SuggestionIterator : public Napi::ObjectWrap<SuggestionIterator> {
75
72
 
76
73
  static void Init(Napi::Env env, Napi::Object exports,
77
74
  ModuleConstructors &constructors) {
78
- Napi::HandleScope scope(env);
79
75
  Napi::Function func = DefineClass(
80
76
  env, "SuggestionIterator",
81
77
  {
@@ -99,7 +95,6 @@ class SuggestionResultSet : public Napi::ObjectWrap<SuggestionResultSet> {
99
95
  explicit SuggestionResultSet(const Napi::CallbackInfo &info)
100
96
  : Napi::ObjectWrap<SuggestionResultSet>(info), resultSet_{nullptr} {
101
97
  Napi::Env env = info.Env();
102
- Napi::HandleScope scope(env);
103
98
 
104
99
  if (!info[0].IsExternal()) {
105
100
  throw Napi::Error::New(env,
@@ -163,7 +158,6 @@ class SuggestionResultSet : public Napi::ObjectWrap<SuggestionResultSet> {
163
158
 
164
159
  static void Init(Napi::Env env, Napi::Object exports,
165
160
  ModuleConstructors &constructors) {
166
- Napi::HandleScope scope(env);
167
161
  Napi::Function func =
168
162
  DefineClass(env, "SuggestionResultSet",
169
163
  {
@@ -185,7 +179,6 @@ class SuggestionSearch : public Napi::ObjectWrap<SuggestionSearch> {
185
179
  explicit SuggestionSearch(const Napi::CallbackInfo &info)
186
180
  : Napi::ObjectWrap<SuggestionSearch>(info), search_{nullptr} {
187
181
  Napi::Env env = info.Env();
188
- Napi::HandleScope scope(env);
189
182
 
190
183
  if (!info[0].IsExternal()) {
191
184
  throw Napi::Error::New(env, "Search must be created internally.");
@@ -232,7 +225,6 @@ class SuggestionSearch : public Napi::ObjectWrap<SuggestionSearch> {
232
225
 
233
226
  static void Init(Napi::Env env, Napi::Object exports,
234
227
  ModuleConstructors &constructors) {
235
- Napi::HandleScope scope(env);
236
228
  Napi::Function func = DefineClass(
237
229
  env, "SuggestionSearch",
238
230
  {
@@ -255,7 +247,6 @@ class SuggestionSearcher : public Napi::ObjectWrap<SuggestionSearcher> {
255
247
  : Napi::ObjectWrap<SuggestionSearcher>(info),
256
248
  suggestionSearcher_{nullptr} {
257
249
  Napi::Env env = info.Env();
258
- Napi::HandleScope scope(env);
259
250
 
260
251
  // TODO(kelvinhammond): Ask about support for suggestions from multiple
261
252
  // archives
@@ -340,7 +331,6 @@ class SuggestionSearcher : public Napi::ObjectWrap<SuggestionSearcher> {
340
331
 
341
332
  static void Init(Napi::Env env, Napi::Object exports,
342
333
  ModuleConstructors &constructors) {
343
- Napi::HandleScope scope(env);
344
334
  Napi::Function func = DefineClass(
345
335
  env, "SuggestionSearcher",
346
336
  {