• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<html lang="en">
3<head>
4  <meta charset="utf-8">
5  <meta name="viewport" content="width=device-width">
6  <meta name="nodejs.org:node-version" content="v14.19.1">
7  <title>C++ addons | Node.js v14.19.1 Documentation</title>
8  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic&display=fallback">
9  <link rel="stylesheet" href="assets/style.css">
10  <link rel="stylesheet" href="assets/hljs.css">
11  <link rel="canonical" href="https://nodejs.org/api/addons.html">
12</head>
13<body class="alt apidoc" id="api-section-addons">
14  <div id="content" class="clearfix">
15    <div id="column2" class="interior">
16      <div id="intro" class="interior">
17        <a href="/" title="Go back to the home page">
18          Node.js
19        </a>
20      </div>
21      <ul>
22<li><a href="documentation.html" class="nav-documentation">About this documentation</a></li>
23<li><a href="synopsis.html" class="nav-synopsis">Usage and example</a></li>
24</ul>
25<hr class="line">
26<ul>
27<li><a href="assert.html" class="nav-assert">Assertion testing</a></li>
28<li><a href="async_hooks.html" class="nav-async_hooks">Async hooks</a></li>
29<li><a href="buffer.html" class="nav-buffer">Buffer</a></li>
30<li><a href="addons.html" class="nav-addons active">C++ addons</a></li>
31<li><a href="n-api.html" class="nav-n-api">C/C++ addons with Node-API</a></li>
32<li><a href="embedding.html" class="nav-embedding">C++ embedder API</a></li>
33<li><a href="child_process.html" class="nav-child_process">Child processes</a></li>
34<li><a href="cluster.html" class="nav-cluster">Cluster</a></li>
35<li><a href="cli.html" class="nav-cli">Command-line options</a></li>
36<li><a href="console.html" class="nav-console">Console</a></li>
37<li><a href="corepack.html" class="nav-corepack">Corepack</a></li>
38<li><a href="crypto.html" class="nav-crypto">Crypto</a></li>
39<li><a href="debugger.html" class="nav-debugger">Debugger</a></li>
40<li><a href="deprecations.html" class="nav-deprecations">Deprecated APIs</a></li>
41<li><a href="diagnostics_channel.html" class="nav-diagnostics_channel">Diagnostics Channel</a></li>
42<li><a href="dns.html" class="nav-dns">DNS</a></li>
43<li><a href="domain.html" class="nav-domain">Domain</a></li>
44<li><a href="errors.html" class="nav-errors">Errors</a></li>
45<li><a href="events.html" class="nav-events">Events</a></li>
46<li><a href="fs.html" class="nav-fs">File system</a></li>
47<li><a href="globals.html" class="nav-globals">Globals</a></li>
48<li><a href="http.html" class="nav-http">HTTP</a></li>
49<li><a href="http2.html" class="nav-http2">HTTP/2</a></li>
50<li><a href="https.html" class="nav-https">HTTPS</a></li>
51<li><a href="inspector.html" class="nav-inspector">Inspector</a></li>
52<li><a href="intl.html" class="nav-intl">Internationalization</a></li>
53<li><a href="modules.html" class="nav-modules">Modules: CommonJS modules</a></li>
54<li><a href="esm.html" class="nav-esm">Modules: ECMAScript modules</a></li>
55<li><a href="module.html" class="nav-module">Modules: <code>module</code> API</a></li>
56<li><a href="packages.html" class="nav-packages">Modules: Packages</a></li>
57<li><a href="net.html" class="nav-net">Net</a></li>
58<li><a href="os.html" class="nav-os">OS</a></li>
59<li><a href="path.html" class="nav-path">Path</a></li>
60<li><a href="perf_hooks.html" class="nav-perf_hooks">Performance hooks</a></li>
61<li><a href="policy.html" class="nav-policy">Policies</a></li>
62<li><a href="process.html" class="nav-process">Process</a></li>
63<li><a href="punycode.html" class="nav-punycode">Punycode</a></li>
64<li><a href="querystring.html" class="nav-querystring">Query strings</a></li>
65<li><a href="readline.html" class="nav-readline">Readline</a></li>
66<li><a href="repl.html" class="nav-repl">REPL</a></li>
67<li><a href="report.html" class="nav-report">Report</a></li>
68<li><a href="stream.html" class="nav-stream">Stream</a></li>
69<li><a href="string_decoder.html" class="nav-string_decoder">String decoder</a></li>
70<li><a href="timers.html" class="nav-timers">Timers</a></li>
71<li><a href="tls.html" class="nav-tls">TLS/SSL</a></li>
72<li><a href="tracing.html" class="nav-tracing">Trace events</a></li>
73<li><a href="tty.html" class="nav-tty">TTY</a></li>
74<li><a href="dgram.html" class="nav-dgram">UDP/datagram</a></li>
75<li><a href="url.html" class="nav-url">URL</a></li>
76<li><a href="util.html" class="nav-util">Utilities</a></li>
77<li><a href="v8.html" class="nav-v8">V8</a></li>
78<li><a href="vm.html" class="nav-vm">VM</a></li>
79<li><a href="wasi.html" class="nav-wasi">WASI</a></li>
80<li><a href="worker_threads.html" class="nav-worker_threads">Worker threads</a></li>
81<li><a href="zlib.html" class="nav-zlib">Zlib</a></li>
82</ul>
83<hr class="line">
84<ul>
85<li><a href="https://github.com/nodejs/node" class="nav-https-github-com-nodejs-node">Code repository and issue tracker</a></li>
86</ul>
87    </div>
88
89    <div id="column1" data-id="addons" class="interior">
90      <header>
91        <div class="header-container">
92          <h1>Node.js v14.19.1 documentation</h1>
93          <button class="theme-toggle-btn" id="theme-toggle-btn" title="Toggle dark mode/light mode" aria-label="Toggle dark mode/light mode" hidden>
94            <svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" height="24" width="24">
95              <path fill="none" d="M0 0h24v24H0z" />
96              <path d="M11.1 12.08c-2.33-4.51-.5-8.48.53-10.07C6.27 2.2 1.98 6.59 1.98 12c0 .14.02.28.02.42.62-.27 1.29-.42 2-.42 1.66 0 3.18.83 4.1 2.15A4.01 4.01 0 0111 18c0 1.52-.87 2.83-2.12 3.51.98.32 2.03.5 3.11.5 3.5 0 6.58-1.8 8.37-4.52-2.36.23-6.98-.97-9.26-5.41z"/>
97              <path d="M7 16h-.18C6.4 14.84 5.3 14 4 14c-1.66 0-3 1.34-3 3s1.34 3 3 3h3c1.1 0 2-.9 2-2s-.9-2-2-2z"/>
98            </svg>
99            <svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" height="24" width="24">
100              <path d="M0 0h24v24H0z" fill="none" />
101              <path d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"/>
102            </svg>
103          </button>
104        </div>
105        <div id="gtoc">
106          <ul>
107            <li>
108              <a href="index.html">Index</a>
109            </li>
110            <li>
111              <a href="all.html">View on single page</a>
112            </li>
113            <li>
114              <a href="addons.json">View as JSON</a>
115            </li>
116
117    <li class="version-picker">
118      <a href="#">View another version <span>&#x25bc;</span></a>
119      <ol class="version-picker"><li><a href="https://nodejs.org/docs/latest-v17.x/api/addons.html">17.x</a></li>
120<li><a href="https://nodejs.org/docs/latest-v16.x/api/addons.html">16.x <b>LTS</b></a></li>
121<li><a href="https://nodejs.org/docs/latest-v15.x/api/addons.html">15.x</a></li>
122<li><a href="https://nodejs.org/docs/latest-v14.x/api/addons.html">14.x <b>LTS</b></a></li>
123<li><a href="https://nodejs.org/docs/latest-v13.x/api/addons.html">13.x</a></li>
124<li><a href="https://nodejs.org/docs/latest-v12.x/api/addons.html">12.x <b>LTS</b></a></li>
125<li><a href="https://nodejs.org/docs/latest-v11.x/api/addons.html">11.x</a></li>
126<li><a href="https://nodejs.org/docs/latest-v10.x/api/addons.html">10.x</a></li>
127<li><a href="https://nodejs.org/docs/latest-v9.x/api/addons.html">9.x</a></li>
128<li><a href="https://nodejs.org/docs/latest-v8.x/api/addons.html">8.x</a></li>
129<li><a href="https://nodejs.org/docs/latest-v7.x/api/addons.html">7.x</a></li>
130<li><a href="https://nodejs.org/docs/latest-v6.x/api/addons.html">6.x</a></li>
131<li><a href="https://nodejs.org/docs/latest-v5.x/api/addons.html">5.x</a></li>
132<li><a href="https://nodejs.org/docs/latest-v4.x/api/addons.html">4.x</a></li>
133<li><a href="https://nodejs.org/docs/latest-v0.12.x/api/addons.html">0.12.x</a></li>
134<li><a href="https://nodejs.org/docs/latest-v0.10.x/api/addons.html">0.10.x</a></li></ol>
135    </li>
136
137            <li class="edit_on_github"><a href="https://github.com/nodejs/node/edit/master/doc/api/addons.md">Edit on GitHub</a></li>
138          </ul>
139        </div>
140        <hr>
141      </header>
142
143      <details id="toc" open><summary>Table of contents</summary><ul>
144<li><a href="#addons_c_addons">C++ addons</a>
145<ul>
146<li><a href="#addons_hello_world">Hello world</a>
147<ul>
148<li><a href="#addons_context_aware_addons">Context-aware addons</a>
149<ul>
150<li><a href="#addons_worker_support">Worker support</a></li>
151</ul>
152</li>
153<li><a href="#addons_building">Building</a></li>
154<li><a href="#addons_linking_to_libraries_included_with_node_js">Linking to libraries included with Node.js</a></li>
155<li><a href="#addons_loading_addons_using_require">Loading addons using <code>require()</code></a></li>
156</ul>
157</li>
158<li><a href="#addons_native_abstractions_for_node_js">Native abstractions for Node.js</a></li>
159<li><span class="stability_2"><a href="#addons_node_api">Node-API</a></span></li>
160<li><a href="#addons_addon_examples">Addon examples</a>
161<ul>
162<li><a href="#addons_function_arguments">Function arguments</a></li>
163<li><a href="#addons_callbacks">Callbacks</a></li>
164<li><a href="#addons_object_factory">Object factory</a></li>
165<li><a href="#addons_function_factory">Function factory</a></li>
166<li><a href="#addons_wrapping_c_objects">Wrapping C++ objects</a></li>
167<li><a href="#addons_factory_of_wrapped_objects">Factory of wrapped objects</a></li>
168<li><a href="#addons_passing_wrapped_objects_around">Passing wrapped objects around</a></li>
169</ul>
170</li>
171</ul>
172</li>
173</ul></details>
174
175      <div id="apicontent">
176        <h2>C++ addons<span><a class="mark" href="#addons_c_addons" id="addons_c_addons">#</a></span></h2>
177
178
179<p><em>Addons</em> are dynamically-linked shared objects written in C++. The
180<a href="modules.html#modules_require_id"><code>require()</code></a> function can load addons as ordinary Node.js modules.
181Addons provide an interface between JavaScript and C/C++ libraries.</p>
182<p>There are three options for implementing addons: Node-API, nan, or direct
183use of internal V8, libuv and Node.js libraries. Unless there is a need for
184direct access to functionality which is not exposed by Node-API, use Node-API.
185Refer to <a href="n-api.html">C/C++ addons with Node-API</a> for more information on
186Node-API.</p>
187<p>When not using Node-API, implementing addons is complicated,
188involving knowledge of several components and APIs:</p>
189<ul>
190<li>
191<p><a href="https://v8.dev/">V8</a>: the C++ library Node.js uses to provide the
192JavaScript implementation. V8 provides the mechanisms for creating objects,
193calling functions, etc. V8's API is documented mostly in the
194<code>v8.h</code> header file (<code>deps/v8/include/v8.h</code> in the Node.js source
195tree), which is also available <a href="https://v8docs.nodesource.com/">online</a>.</p>
196</li>
197<li>
198<p><a href="https://github.com/libuv/libuv">libuv</a>: The C library that implements the Node.js event loop, its worker
199threads and all of the asynchronous behaviors of the platform. It also
200serves as a cross-platform abstraction library, giving easy, POSIX-like
201access across all major operating systems to many common system tasks, such
202as interacting with the filesystem, sockets, timers, and system events. libuv
203also provides a threading abstraction similar to POSIX threads for
204more sophisticated asynchronous addons that need to move beyond the
205standard event loop. Addon authors should
206avoid blocking the event loop with I/O or other time-intensive tasks by
207offloading work via libuv to non-blocking system operations, worker threads,
208or a custom use of libuv threads.</p>
209</li>
210<li>
211<p>Internal Node.js libraries. Node.js itself exports C++ APIs that addons can
212use, the most important of which is the <code>node::ObjectWrap</code> class.</p>
213</li>
214<li>
215<p>Node.js includes other statically linked libraries including OpenSSL. These
216other libraries are located in the <code>deps/</code> directory in the Node.js source
217tree. Only the libuv, OpenSSL, V8 and zlib symbols are purposefully
218re-exported by Node.js and may be used to various extents by addons. See
219<a href="#addons_linking_to_libraries_included_with_node_js">Linking to libraries included with Node.js</a> for additional information.</p>
220</li>
221</ul>
222<p>All of the following examples are available for <a href="https://github.com/nodejs/node-addon-examples">download</a> and may
223be used as the starting-point for an addon.</p>
224<section><h3>Hello world<span><a class="mark" href="#addons_hello_world" id="addons_hello_world">#</a></span></h3>
225<p>This "Hello world" example is a simple addon, written in C++, that is the
226equivalent of the following JavaScript code:</p>
227<pre><code class="language-js"><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>.<span class="hljs-property">hello</span> = <span class="hljs-function">() =></span> <span class="hljs-string">'world'</span>;</code></pre>
228<p>First, create the file <code>hello.cc</code>:</p>
229<pre><code class="language-cpp"><span class="hljs-comment">// hello.cc</span>
230<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
231
232<span class="hljs-keyword">namespace</span> demo {
233
234<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
235<span class="hljs-keyword">using</span> v8::Isolate;
236<span class="hljs-keyword">using</span> v8::Local;
237<span class="hljs-keyword">using</span> v8::Object;
238<span class="hljs-keyword">using</span> v8::String;
239<span class="hljs-keyword">using</span> v8::Value;
240
241<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Method</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
242  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
243  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(String::<span class="hljs-built_in">NewFromUtf8</span>(
244      isolate, <span class="hljs-string">"world"</span>).<span class="hljs-built_in">ToLocalChecked</span>());
245}
246
247<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Initialize</span><span class="hljs-params">(Local&#x3C;Object> exports)</span> </span>{
248  <span class="hljs-built_in">NODE_SET_METHOD</span>(exports, <span class="hljs-string">"hello"</span>, Method);
249}
250
251<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, Initialize)
252
253}  <span class="hljs-comment">// namespace demo</span></code></pre>
254<p>All Node.js addons must export an initialization function following
255the pattern:</p>
256<pre><code class="language-cpp"><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Initialize</span><span class="hljs-params">(Local&#x3C;Object> exports)</span></span>;
257<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, Initialize)</code></pre>
258<p>There is no semi-colon after <code>NODE_MODULE</code> as it's not a function (see
259<code>node.h</code>).</p>
260<p>The <code>module_name</code> must match the filename of the final binary (excluding
261the <code>.node</code> suffix).</p>
262<p>In the <code>hello.cc</code> example, then, the initialization function is <code>Initialize</code>
263and the addon module name is <code>addon</code>.</p>
264<p>When building addons with <code>node-gyp</code>, using the macro <code>NODE_GYP_MODULE_NAME</code> as
265the first parameter of <code>NODE_MODULE()</code> will ensure that the name of the final
266binary will be passed to <code>NODE_MODULE()</code>.</p>
267<h4>Context-aware addons<span><a class="mark" href="#addons_context_aware_addons" id="addons_context_aware_addons">#</a></span></h4>
268<p>There are environments in which Node.js addons may need to be loaded multiple
269times in multiple contexts. For example, the <a href="https://electronjs.org/">Electron</a> runtime runs multiple
270instances of Node.js in a single process. Each instance will have its own
271<code>require()</code> cache, and thus each instance will need a native addon to behave
272correctly when loaded via <code>require()</code>. This means that the addon
273must support multiple initializations.</p>
274<p>A context-aware addon can be constructed by using the macro
275<code>NODE_MODULE_INITIALIZER</code>, which expands to the name of a function which Node.js
276will expect to find when it loads an addon. An addon can thus be initialized as
277in the following example:</p>
278<pre><code class="language-cpp"><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> v8;
279
280<span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> <span class="hljs-function">NODE_MODULE_EXPORT <span class="hljs-type">void</span>
281<span class="hljs-title">NODE_MODULE_INITIALIZER</span><span class="hljs-params">(Local&#x3C;Object> exports,
282                        Local&#x3C;Value> <span class="hljs-keyword">module</span>,
283                        Local&#x3C;Context> context)</span> </span>{
284  <span class="hljs-comment">/* Perform addon initialization steps here. */</span>
285}</code></pre>
286<p>Another option is to use the macro <code>NODE_MODULE_INIT()</code>, which will also
287construct a context-aware addon. Unlike <code>NODE_MODULE()</code>, which is used to
288construct an addon around a given addon initializer function,
289<code>NODE_MODULE_INIT()</code> serves as the declaration of such an initializer to be
290followed by a function body.</p>
291<p>The following three variables may be used inside the function body following an
292invocation of <code>NODE_MODULE_INIT()</code>:</p>
293<ul>
294<li><code>Local&#x3C;Object> exports</code>,</li>
295<li><code>Local&#x3C;Value> module</code>, and</li>
296<li><code>Local&#x3C;Context> context</code></li>
297</ul>
298<p>The choice to build a context-aware addon carries with it the responsibility of
299carefully managing global static data. Since the addon may be loaded multiple
300times, potentially even from different threads, any global static data stored
301in the addon must be properly protected, and must not contain any persistent
302references to JavaScript objects. The reason for this is that JavaScript
303objects are only valid in one context, and will likely cause a crash when
304accessed from the wrong context or from a different thread than the one on which
305they were created.</p>
306<p>The context-aware addon can be structured to avoid global static data by
307performing the following steps:</p>
308<ul>
309<li>Define a class which will hold per-addon-instance data and which has a static
310member of the form
311<pre><code class="language-cpp"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">DeleteInstance</span><span class="hljs-params">(<span class="hljs-type">void</span>* data)</span> </span>{
312  <span class="hljs-comment">// Cast `data` to an instance of the class and delete it.</span>
313}</code></pre>
314</li>
315<li>Heap-allocate an instance of this class in the addon initializer. This can be
316accomplished using the <code>new</code> keyword.</li>
317<li>Call <code>node::AddEnvironmentCleanupHook()</code>, passing it the above-created
318instance and a pointer to <code>DeleteInstance()</code>. This will ensure the instance is
319deleted when the environment is torn down.</li>
320<li>Store the instance of the class in a <code>v8::External</code>, and</li>
321<li>Pass the <code>v8::External</code> to all methods exposed to JavaScript by passing it
322to <code>v8::FunctionTemplate::New()</code> or <code>v8::Function::New()</code> which creates the
323native-backed JavaScript functions. The third parameter of
324<code>v8::FunctionTemplate::New()</code> or <code>v8::Function::New()</code>  accepts the
325<code>v8::External</code> and makes it available in the native callback using the
326<code>v8::FunctionCallbackInfo::Data()</code> method.</li>
327</ul>
328<p>This will ensure that the per-addon-instance data reaches each binding that can
329be called from JavaScript. The per-addon-instance data must also be passed into
330any asynchronous callbacks the addon may create.</p>
331<p>The following example illustrates the implementation of a context-aware addon:</p>
332<pre><code class="language-cpp"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
333
334<span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> v8;
335
336<span class="hljs-keyword">class</span> <span class="hljs-title class_">AddonData</span> {
337 <span class="hljs-keyword">public</span>:
338  <span class="hljs-function"><span class="hljs-keyword">explicit</span> <span class="hljs-title">AddonData</span><span class="hljs-params">(Isolate* isolate)</span>:
339      call_count(<span class="hljs-number">0</span>) {</span>
340    <span class="hljs-comment">// Ensure this per-addon-instance data is deleted at environment cleanup.</span>
341    node::<span class="hljs-built_in">AddEnvironmentCleanupHook</span>(isolate, DeleteInstance, <span class="hljs-keyword">this</span>);
342  }
343
344  <span class="hljs-comment">// Per-addon data.</span>
345  <span class="hljs-type">int</span> call_count;
346
347  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">DeleteInstance</span><span class="hljs-params">(<span class="hljs-type">void</span>* data)</span> </span>{
348    <span class="hljs-keyword">delete</span> <span class="hljs-built_in">static_cast</span>&#x3C;AddonData*>(data);
349  }
350};
351
352<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">Method</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; info)</span> </span>{
353  <span class="hljs-comment">// Retrieve the per-addon-instance data.</span>
354  AddonData* data =
355      <span class="hljs-built_in">reinterpret_cast</span>&#x3C;AddonData*>(info.<span class="hljs-built_in">Data</span>().<span class="hljs-built_in">As</span>&#x3C;External>()-><span class="hljs-built_in">Value</span>());
356  data->call_count++;
357  info.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>((<span class="hljs-type">double</span>)data->call_count);
358}
359
360<span class="hljs-comment">// Initialize this addon to be context-aware.</span>
361<span class="hljs-built_in">NODE_MODULE_INIT</span>(<span class="hljs-comment">/* exports, module, context */</span>) {
362  Isolate* isolate = context-><span class="hljs-built_in">GetIsolate</span>();
363
364  <span class="hljs-comment">// Create a new instance of `AddonData` for this instance of the addon and</span>
365  <span class="hljs-comment">// tie its life cycle to that of the Node.js environment.</span>
366  AddonData* data = <span class="hljs-keyword">new</span> <span class="hljs-built_in">AddonData</span>(isolate);
367
368  <span class="hljs-comment">// Wrap the data in a `v8::External` so we can pass it to the method we</span>
369  <span class="hljs-comment">// expose.</span>
370  Local&#x3C;External> external = External::<span class="hljs-built_in">New</span>(isolate, data);
371
372  <span class="hljs-comment">// Expose the method `Method` to JavaScript, and make sure it receives the</span>
373  <span class="hljs-comment">// per-addon-instance data we created above by passing `external` as the</span>
374  <span class="hljs-comment">// third parameter to the `FunctionTemplate` constructor.</span>
375  exports-><span class="hljs-built_in">Set</span>(context,
376               String::<span class="hljs-built_in">NewFromUtf8</span>(isolate, <span class="hljs-string">"method"</span>).<span class="hljs-built_in">ToLocalChecked</span>(),
377               FunctionTemplate::<span class="hljs-built_in">New</span>(isolate, Method, external)
378                  -><span class="hljs-built_in">GetFunction</span>(context).<span class="hljs-built_in">ToLocalChecked</span>()).<span class="hljs-built_in">FromJust</span>();
379}</code></pre>
380<h5>Worker support<span><a class="mark" href="#addons_worker_support" id="addons_worker_support">#</a></span></h5>
381<div class="api_metadata">
382<details class="changelog"><summary>History</summary>
383<table>
384<tbody><tr><th>Version</th><th>Changes</th></tr>
385<tr><td>v14.8.0</td>
386<td><p>Cleanup hooks may now be asynchronous.</p></td></tr>
387</tbody></table>
388</details>
389</div>
390<p>In order to be loaded from multiple Node.js environments,
391such as a main thread and a Worker thread, an add-on needs to either:</p>
392<ul>
393<li>Be an Node-API addon, or</li>
394<li>Be declared as context-aware using <code>NODE_MODULE_INIT()</code> as described above</li>
395</ul>
396<p>In order to support <a href="worker_threads.html#worker_threads_class_worker"><code>Worker</code></a> threads, addons need to clean up any resources
397they may have allocated when such a thread exists. This can be achieved through
398the usage of the <code>AddEnvironmentCleanupHook()</code> function:</p>
399<pre><code class="language-cpp"><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">AddEnvironmentCleanupHook</span><span class="hljs-params">(v8::Isolate* isolate,
400                               <span class="hljs-type">void</span> (*fun)(<span class="hljs-type">void</span>* arg),
401                               <span class="hljs-type">void</span>* arg)</span></span>;</code></pre>
402<p>This function adds a hook that will run before a given Node.js instance shuts
403down. If necessary, such hooks can be removed before they are run using
404<code>RemoveEnvironmentCleanupHook()</code>, which has the same signature. Callbacks are
405run in last-in first-out order.</p>
406<p>If necessary, there is an additional pair of <code>AddEnvironmentCleanupHook()</code>
407and <code>RemoveEnvironmentCleanupHook()</code> overloads, where the cleanup hook takes a
408callback function. This can be used for shutting down asynchronous resources,
409such as any libuv handles registered by the addon.</p>
410<p>The following <code>addon.cc</code> uses <code>AddEnvironmentCleanupHook</code>:</p>
411<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
412<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
413<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;assert.h></span></span>
414<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;stdlib.h></span></span>
415
416<span class="hljs-keyword">using</span> node::AddEnvironmentCleanupHook;
417<span class="hljs-keyword">using</span> v8::HandleScope;
418<span class="hljs-keyword">using</span> v8::Isolate;
419<span class="hljs-keyword">using</span> v8::Local;
420<span class="hljs-keyword">using</span> v8::Object;
421
422<span class="hljs-comment">// Note: In a real-world application, do not rely on static/global data.</span>
423<span class="hljs-keyword">static</span> <span class="hljs-type">char</span> cookie[] = <span class="hljs-string">"yum yum"</span>;
424<span class="hljs-keyword">static</span> <span class="hljs-type">int</span> cleanup_cb1_called = <span class="hljs-number">0</span>;
425<span class="hljs-keyword">static</span> <span class="hljs-type">int</span> cleanup_cb2_called = <span class="hljs-number">0</span>;
426
427<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">cleanup_cb1</span><span class="hljs-params">(<span class="hljs-type">void</span>* arg)</span> </span>{
428  Isolate* isolate = <span class="hljs-built_in">static_cast</span>&#x3C;Isolate*>(arg);
429  <span class="hljs-function">HandleScope <span class="hljs-title">scope</span><span class="hljs-params">(isolate)</span></span>;
430  Local&#x3C;Object> obj = Object::<span class="hljs-built_in">New</span>(isolate);
431  <span class="hljs-built_in">assert</span>(!obj.<span class="hljs-built_in">IsEmpty</span>());  <span class="hljs-comment">// assert VM is still alive</span>
432  <span class="hljs-built_in">assert</span>(obj-><span class="hljs-built_in">IsObject</span>());
433  cleanup_cb1_called++;
434}
435
436<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">cleanup_cb2</span><span class="hljs-params">(<span class="hljs-type">void</span>* arg)</span> </span>{
437  <span class="hljs-built_in">assert</span>(arg == <span class="hljs-built_in">static_cast</span>&#x3C;<span class="hljs-type">void</span>*>(cookie));
438  cleanup_cb2_called++;
439}
440
441<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">sanity_check</span><span class="hljs-params">(<span class="hljs-type">void</span>*)</span> </span>{
442  <span class="hljs-built_in">assert</span>(cleanup_cb1_called == <span class="hljs-number">1</span>);
443  <span class="hljs-built_in">assert</span>(cleanup_cb2_called == <span class="hljs-number">1</span>);
444}
445
446<span class="hljs-comment">// Initialize this addon to be context-aware.</span>
447<span class="hljs-built_in">NODE_MODULE_INIT</span>(<span class="hljs-comment">/* exports, module, context */</span>) {
448  Isolate* isolate = context-><span class="hljs-built_in">GetIsolate</span>();
449
450  <span class="hljs-built_in">AddEnvironmentCleanupHook</span>(isolate, sanity_check, <span class="hljs-literal">nullptr</span>);
451  <span class="hljs-built_in">AddEnvironmentCleanupHook</span>(isolate, cleanup_cb2, cookie);
452  <span class="hljs-built_in">AddEnvironmentCleanupHook</span>(isolate, cleanup_cb1, isolate);
453}</code></pre>
454<p>Test in JavaScript by running:</p>
455<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
456<span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);</code></pre>
457<h4>Building<span><a class="mark" href="#addons_building" id="addons_building">#</a></span></h4>
458<p>Once the source code has been written, it must be compiled into the binary
459<code>addon.node</code> file. To do so, create a file called <code>binding.gyp</code> in the
460top-level of the project describing the build configuration of the module
461using a JSON-like format. This file is used by <a href="https://github.com/nodejs/node-gyp">node-gyp</a>, a tool written
462specifically to compile Node.js addons.</p>
463<pre><code class="language-json"><span class="hljs-punctuation">{</span>
464  <span class="hljs-attr">"targets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
465    <span class="hljs-punctuation">{</span>
466      <span class="hljs-attr">"target_name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"addon"</span><span class="hljs-punctuation">,</span>
467      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> <span class="hljs-string">"hello.cc"</span> <span class="hljs-punctuation">]</span>
468    <span class="hljs-punctuation">}</span>
469  <span class="hljs-punctuation">]</span>
470<span class="hljs-punctuation">}</span></code></pre>
471<p>A version of the <code>node-gyp</code> utility is bundled and distributed with
472Node.js as part of <code>npm</code>. This version is not made directly available for
473developers to use and is intended only to support the ability to use the
474<code>npm install</code> command to compile and install addons. Developers who wish to
475use <code>node-gyp</code> directly can install it using the command
476<code>npm install -g node-gyp</code>. See the <code>node-gyp</code> <a href="https://github.com/nodejs/node-gyp#installation">installation instructions</a> for
477more information, including platform-specific requirements.</p>
478<p>Once the <code>binding.gyp</code> file has been created, use <code>node-gyp configure</code> to
479generate the appropriate project build files for the current platform. This
480will generate either a <code>Makefile</code> (on Unix platforms) or a <code>vcxproj</code> file
481(on Windows) in the <code>build/</code> directory.</p>
482<p>Next, invoke the <code>node-gyp build</code> command to generate the compiled <code>addon.node</code>
483file. This will be put into the <code>build/Release/</code> directory.</p>
484<p>When using <code>npm install</code> to install a Node.js addon, npm uses its own bundled
485version of <code>node-gyp</code> to perform this same set of actions, generating a
486compiled version of the addon for the user's platform on demand.</p>
487<p>Once built, the binary addon can be used from within Node.js by pointing
488<a href="modules.html#modules_require_id"><code>require()</code></a> to the built <code>addon.node</code> module:</p>
489<pre><code class="language-js"><span class="hljs-comment">// hello.js</span>
490<span class="hljs-keyword">const</span> addon = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
491
492<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(addon.<span class="hljs-title function_">hello</span>());
493<span class="hljs-comment">// Prints: 'world'</span></code></pre>
494<p>Because the exact path to the compiled addon binary can vary depending on how
495it is compiled (i.e. sometimes it may be in <code>./build/Debug/</code>), addons can use
496the <a href="https://github.com/TooTallNate/node-bindings">bindings</a> package to load the compiled module.</p>
497<p>While the <code>bindings</code> package implementation is more sophisticated in how it
498locates addon modules, it is essentially using a <code>try…catch</code> pattern similar to:</p>
499<pre><code class="language-js"><span class="hljs-keyword">try</span> {
500  <span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon.node'</span>);
501} <span class="hljs-keyword">catch</span> (err) {
502  <span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Debug/addon.node'</span>);
503}</code></pre>
504<h4>Linking to libraries included with Node.js<span><a class="mark" href="#addons_linking_to_libraries_included_with_node_js" id="addons_linking_to_libraries_included_with_node_js">#</a></span></h4>
505<p>Node.js uses statically linked libraries such as V8, libuv and OpenSSL. All
506addons are required to link to V8 and may link to any of the other dependencies
507as well. Typically, this is as simple as including the appropriate
508<code>#include &#x3C;...></code> statements (e.g. <code>#include &#x3C;v8.h></code>) and <code>node-gyp</code> will locate
509the appropriate headers automatically. However, there are a few caveats to be
510aware of:</p>
511<ul>
512<li>
513<p>When <code>node-gyp</code> runs, it will detect the specific release version of Node.js
514and download either the full source tarball or just the headers. If the full
515source is downloaded, addons will have complete access to the full set of
516Node.js dependencies. However, if only the Node.js headers are downloaded,
517then only the symbols exported by Node.js will be available.</p>
518</li>
519<li>
520<p><code>node-gyp</code> can be run using the <code>--nodedir</code> flag pointing at a local Node.js
521source image. Using this option, the addon will have access to the full set of
522dependencies.</p>
523</li>
524</ul>
525<h4>Loading addons using <code>require()</code><span><a class="mark" href="#addons_loading_addons_using_require" id="addons_loading_addons_using_require">#</a></span></h4>
526<p>The filename extension of the compiled addon binary is <code>.node</code> (as opposed
527to <code>.dll</code> or <code>.so</code>). The <a href="modules.html#modules_require_id"><code>require()</code></a> function is written to look for
528files with the <code>.node</code> file extension and initialize those as dynamically-linked
529libraries.</p>
530<p>When calling <a href="modules.html#modules_require_id"><code>require()</code></a>, the <code>.node</code> extension can usually be
531omitted and Node.js will still find and initialize the addon. One caveat,
532however, is that Node.js will first attempt to locate and load modules or
533JavaScript files that happen to share the same base name. For instance, if
534there is a file <code>addon.js</code> in the same directory as the binary <code>addon.node</code>,
535then <a href="modules.html#modules_require_id"><code>require('addon')</code></a> will give precedence to the <code>addon.js</code> file
536and load it instead.</p>
537</section><section><h3>Native abstractions for Node.js<span><a class="mark" href="#addons_native_abstractions_for_node_js" id="addons_native_abstractions_for_node_js">#</a></span></h3>
538<p>Each of the examples illustrated in this document directly use the
539Node.js and V8 APIs for implementing addons. The V8 API can, and has, changed
540dramatically from one V8 release to the next (and one major Node.js release to
541the next). With each change, addons may need to be updated and recompiled in
542order to continue functioning. The Node.js release schedule is designed to
543minimize the frequency and impact of such changes but there is little that
544Node.js can do to ensure stability of the V8 APIs.</p>
545<p>The <a href="https://github.com/nodejs/nan">Native Abstractions for Node.js</a> (or <code>nan</code>) provide a set of tools that
546addon developers are recommended to use to keep compatibility between past and
547future releases of V8 and Node.js. See the <code>nan</code> <a href="https://github.com/nodejs/nan/tree/HEAD/examples/">examples</a> for an
548illustration of how it can be used.</p>
549</section><section><h3>Node-API<span><a class="mark" href="#addons_node_api" id="addons_node_api">#</a></span></h3>
550<p></p><div class="api_stability api_stability_2"><a href="documentation.html#documentation_stability_index">Stability: 2</a> - Stable</div><p></p>
551<p>Node-API is an API for building native addons. It is independent from
552the underlying JavaScript runtime (e.g. V8) and is maintained as part of
553Node.js itself. This API will be Application Binary Interface (ABI) stable
554across versions of Node.js. It is intended to insulate addons from
555changes in the underlying JavaScript engine and allow modules
556compiled for one version to run on later versions of Node.js without
557recompilation. Addons are built/packaged with the same approach/tools
558outlined in this document (node-gyp, etc.). The only difference is the
559set of APIs that are used by the native code. Instead of using the V8
560or <a href="https://github.com/nodejs/nan">Native Abstractions for Node.js</a> APIs, the functions available
561in the Node-API are used.</p>
562<p>Creating and maintaining an addon that benefits from the ABI stability
563provided by Node-API carries with it certain
564<a href="n-api.html#n_api_implications_of_abi_stability">implementation considerations</a>.</p>
565<p>To use Node-API in the above "Hello world" example, replace the content of
566<code>hello.cc</code> with the following. All other instructions remain the same.</p>
567<pre><code class="language-cpp"><span class="hljs-comment">// hello.cc using Node-API</span>
568<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node_api.h></span></span>
569
570<span class="hljs-keyword">namespace</span> demo {
571
572<span class="hljs-function">napi_value <span class="hljs-title">Method</span><span class="hljs-params">(napi_env env, napi_callback_info args)</span> </span>{
573  napi_value greeting;
574  napi_status status;
575
576  status = <span class="hljs-built_in">napi_create_string_utf8</span>(env, <span class="hljs-string">"world"</span>, NAPI_AUTO_LENGTH, &#x26;greeting);
577  <span class="hljs-keyword">if</span> (status != napi_ok) <span class="hljs-keyword">return</span> <span class="hljs-literal">nullptr</span>;
578  <span class="hljs-keyword">return</span> greeting;
579}
580
581<span class="hljs-function">napi_value <span class="hljs-title">init</span><span class="hljs-params">(napi_env env, napi_value exports)</span> </span>{
582  napi_status status;
583  napi_value fn;
584
585  status = <span class="hljs-built_in">napi_create_function</span>(env, <span class="hljs-literal">nullptr</span>, <span class="hljs-number">0</span>, Method, <span class="hljs-literal">nullptr</span>, &#x26;fn);
586  <span class="hljs-keyword">if</span> (status != napi_ok) <span class="hljs-keyword">return</span> <span class="hljs-literal">nullptr</span>;
587
588  status = <span class="hljs-built_in">napi_set_named_property</span>(env, exports, <span class="hljs-string">"hello"</span>, fn);
589  <span class="hljs-keyword">if</span> (status != napi_ok) <span class="hljs-keyword">return</span> <span class="hljs-literal">nullptr</span>;
590  <span class="hljs-keyword">return</span> exports;
591}
592
593<span class="hljs-built_in">NAPI_MODULE</span>(NODE_GYP_MODULE_NAME, init)
594
595}  <span class="hljs-comment">// namespace demo</span></code></pre>
596<p>The functions available and how to use them are documented in
597<a href="n-api.html">C/C++ addons with Node-API</a>.</p>
598</section><section><h3>Addon examples<span><a class="mark" href="#addons_addon_examples" id="addons_addon_examples">#</a></span></h3>
599<p>Following are some example addons intended to help developers get started. The
600examples use the V8 APIs. Refer to the online <a href="https://v8docs.nodesource.com/">V8 reference</a>
601for help with the various V8 calls, and V8's <a href="https://github.com/v8/v8/wiki/Embedder&#x27;s%20Guide">Embedder's Guide</a> for an
602explanation of several concepts used such as handles, scopes, function
603templates, etc.</p>
604<p>Each of these examples using the following <code>binding.gyp</code> file:</p>
605<pre><code class="language-json"><span class="hljs-punctuation">{</span>
606  <span class="hljs-attr">"targets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
607    <span class="hljs-punctuation">{</span>
608      <span class="hljs-attr">"target_name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"addon"</span><span class="hljs-punctuation">,</span>
609      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> <span class="hljs-string">"addon.cc"</span> <span class="hljs-punctuation">]</span>
610    <span class="hljs-punctuation">}</span>
611  <span class="hljs-punctuation">]</span>
612<span class="hljs-punctuation">}</span></code></pre>
613<p>In cases where there is more than one <code>.cc</code> file, simply add the additional
614filename to the <code>sources</code> array:</p>
615<pre><code class="language-json"><span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"addon.cc"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"myexample.cc"</span><span class="hljs-punctuation">]</span></code></pre>
616<p>Once the <code>binding.gyp</code> file is ready, the example addons can be configured and
617built using <code>node-gyp</code>:</p>
618<pre><code class="language-console"><span class="hljs-meta">$ </span><span class="language-bash">node-gyp configure build</span></code></pre>
619<h4>Function arguments<span><a class="mark" href="#addons_function_arguments" id="addons_function_arguments">#</a></span></h4>
620<p>Addons will typically expose objects and functions that can be accessed from
621JavaScript running within Node.js. When functions are invoked from JavaScript,
622the input arguments and return value must be mapped to and from the C/C++
623code.</p>
624<p>The following example illustrates how to read function arguments passed from
625JavaScript and how to return a result:</p>
626<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
627<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
628
629<span class="hljs-keyword">namespace</span> demo {
630
631<span class="hljs-keyword">using</span> v8::Exception;
632<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
633<span class="hljs-keyword">using</span> v8::Isolate;
634<span class="hljs-keyword">using</span> v8::Local;
635<span class="hljs-keyword">using</span> v8::Number;
636<span class="hljs-keyword">using</span> v8::Object;
637<span class="hljs-keyword">using</span> v8::String;
638<span class="hljs-keyword">using</span> v8::Value;
639
640<span class="hljs-comment">// This is the implementation of the "add" method</span>
641<span class="hljs-comment">// Input arguments are passed using the</span>
642<span class="hljs-comment">// const FunctionCallbackInfo&#x3C;Value>&#x26; args struct</span>
643<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Add</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
644  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
645
646  <span class="hljs-comment">// Check the number of arguments passed.</span>
647  <span class="hljs-keyword">if</span> (args.<span class="hljs-built_in">Length</span>() &#x3C; <span class="hljs-number">2</span>) {
648    <span class="hljs-comment">// Throw an Error that is passed back to JavaScript</span>
649    isolate-><span class="hljs-built_in">ThrowException</span>(Exception::<span class="hljs-built_in">TypeError</span>(
650        String::<span class="hljs-built_in">NewFromUtf8</span>(isolate,
651                            <span class="hljs-string">"Wrong number of arguments"</span>).<span class="hljs-built_in">ToLocalChecked</span>()));
652    <span class="hljs-keyword">return</span>;
653  }
654
655  <span class="hljs-comment">// Check the argument types</span>
656  <span class="hljs-keyword">if</span> (!args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">IsNumber</span>() || !args[<span class="hljs-number">1</span>]-><span class="hljs-built_in">IsNumber</span>()) {
657    isolate-><span class="hljs-built_in">ThrowException</span>(Exception::<span class="hljs-built_in">TypeError</span>(
658        String::<span class="hljs-built_in">NewFromUtf8</span>(isolate,
659                            <span class="hljs-string">"Wrong arguments"</span>).<span class="hljs-built_in">ToLocalChecked</span>()));
660    <span class="hljs-keyword">return</span>;
661  }
662
663  <span class="hljs-comment">// Perform the operation</span>
664  <span class="hljs-type">double</span> value =
665      args[<span class="hljs-number">0</span>].<span class="hljs-built_in">As</span>&#x3C;Number>()-><span class="hljs-built_in">Value</span>() + args[<span class="hljs-number">1</span>].<span class="hljs-built_in">As</span>&#x3C;Number>()-><span class="hljs-built_in">Value</span>();
666  Local&#x3C;Number> num = Number::<span class="hljs-built_in">New</span>(isolate, value);
667
668  <span class="hljs-comment">// Set the return value (using the passed in</span>
669  <span class="hljs-comment">// FunctionCallbackInfo&#x3C;Value>&#x26;)</span>
670  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(num);
671}
672
673<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Init</span><span class="hljs-params">(Local&#x3C;Object> exports)</span> </span>{
674  <span class="hljs-built_in">NODE_SET_METHOD</span>(exports, <span class="hljs-string">"add"</span>, Add);
675}
676
677<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, Init)
678
679}  <span class="hljs-comment">// namespace demo</span></code></pre>
680<p>Once compiled, the example addon can be required and used from within Node.js:</p>
681<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
682<span class="hljs-keyword">const</span> addon = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
683
684<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'This should be eight:'</span>, addon.<span class="hljs-title function_">add</span>(<span class="hljs-number">3</span>, <span class="hljs-number">5</span>));</code></pre>
685<h4>Callbacks<span><a class="mark" href="#addons_callbacks" id="addons_callbacks">#</a></span></h4>
686<p>It is common practice within addons to pass JavaScript functions to a C++
687function and execute them from there. The following example illustrates how
688to invoke such callbacks:</p>
689<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
690<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
691
692<span class="hljs-keyword">namespace</span> demo {
693
694<span class="hljs-keyword">using</span> v8::Context;
695<span class="hljs-keyword">using</span> v8::Function;
696<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
697<span class="hljs-keyword">using</span> v8::Isolate;
698<span class="hljs-keyword">using</span> v8::Local;
699<span class="hljs-keyword">using</span> v8::Null;
700<span class="hljs-keyword">using</span> v8::Object;
701<span class="hljs-keyword">using</span> v8::String;
702<span class="hljs-keyword">using</span> v8::Value;
703
704<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">RunCallback</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
705  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
706  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
707  Local&#x3C;Function> cb = Local&#x3C;Function>::<span class="hljs-built_in">Cast</span>(args[<span class="hljs-number">0</span>]);
708  <span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> argc = <span class="hljs-number">1</span>;
709  Local&#x3C;Value> argv[argc] = {
710      String::<span class="hljs-built_in">NewFromUtf8</span>(isolate,
711                          <span class="hljs-string">"hello world"</span>).<span class="hljs-built_in">ToLocalChecked</span>() };
712  cb-><span class="hljs-built_in">Call</span>(context, <span class="hljs-built_in">Null</span>(isolate), argc, argv).<span class="hljs-built_in">ToLocalChecked</span>();
713}
714
715<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Init</span><span class="hljs-params">(Local&#x3C;Object> exports, Local&#x3C;Object> <span class="hljs-keyword">module</span>)</span> </span>{
716  <span class="hljs-built_in">NODE_SET_METHOD</span>(<span class="hljs-keyword">module</span>, <span class="hljs-string">"exports"</span>, RunCallback);
717}
718
719<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, Init)
720
721}  <span class="hljs-comment">// namespace demo</span></code></pre>
722<p>This example uses a two-argument form of <code>Init()</code> that receives the full
723<code>module</code> object as the second argument. This allows the addon to completely
724overwrite <code>exports</code> with a single function instead of adding the function as a
725property of <code>exports</code>.</p>
726<p>To test it, run the following JavaScript:</p>
727<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
728<span class="hljs-keyword">const</span> addon = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
729
730<span class="hljs-title function_">addon</span>(<span class="hljs-function">(<span class="hljs-params">msg</span>) =></span> {
731  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(msg);
732<span class="hljs-comment">// Prints: 'hello world'</span>
733});</code></pre>
734<p>In this example, the callback function is invoked synchronously.</p>
735<h4>Object factory<span><a class="mark" href="#addons_object_factory" id="addons_object_factory">#</a></span></h4>
736<p>Addons can create and return new objects from within a C++ function as
737illustrated in the following example. An object is created and returned with a
738property <code>msg</code> that echoes the string passed to <code>createObject()</code>:</p>
739<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
740<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
741
742<span class="hljs-keyword">namespace</span> demo {
743
744<span class="hljs-keyword">using</span> v8::Context;
745<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
746<span class="hljs-keyword">using</span> v8::Isolate;
747<span class="hljs-keyword">using</span> v8::Local;
748<span class="hljs-keyword">using</span> v8::Object;
749<span class="hljs-keyword">using</span> v8::String;
750<span class="hljs-keyword">using</span> v8::Value;
751
752<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">CreateObject</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
753  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
754  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
755
756  Local&#x3C;Object> obj = Object::<span class="hljs-built_in">New</span>(isolate);
757  obj-><span class="hljs-built_in">Set</span>(context,
758           String::<span class="hljs-built_in">NewFromUtf8</span>(isolate,
759                               <span class="hljs-string">"msg"</span>).<span class="hljs-built_in">ToLocalChecked</span>(),
760                               args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">ToString</span>(context).<span class="hljs-built_in">ToLocalChecked</span>())
761           .<span class="hljs-built_in">FromJust</span>();
762
763  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(obj);
764}
765
766<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Init</span><span class="hljs-params">(Local&#x3C;Object> exports, Local&#x3C;Object> <span class="hljs-keyword">module</span>)</span> </span>{
767  <span class="hljs-built_in">NODE_SET_METHOD</span>(<span class="hljs-keyword">module</span>, <span class="hljs-string">"exports"</span>, CreateObject);
768}
769
770<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, Init)
771
772}  <span class="hljs-comment">// namespace demo</span></code></pre>
773<p>To test it in JavaScript:</p>
774<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
775<span class="hljs-keyword">const</span> addon = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
776
777<span class="hljs-keyword">const</span> obj1 = <span class="hljs-title function_">addon</span>(<span class="hljs-string">'hello'</span>);
778<span class="hljs-keyword">const</span> obj2 = <span class="hljs-title function_">addon</span>(<span class="hljs-string">'world'</span>);
779<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj1.<span class="hljs-property">msg</span>, obj2.<span class="hljs-property">msg</span>);
780<span class="hljs-comment">// Prints: 'hello world'</span></code></pre>
781<h4>Function factory<span><a class="mark" href="#addons_function_factory" id="addons_function_factory">#</a></span></h4>
782<p>Another common scenario is creating JavaScript functions that wrap C++
783functions and returning those back to JavaScript:</p>
784<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
785<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
786
787<span class="hljs-keyword">namespace</span> demo {
788
789<span class="hljs-keyword">using</span> v8::Context;
790<span class="hljs-keyword">using</span> v8::Function;
791<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
792<span class="hljs-keyword">using</span> v8::FunctionTemplate;
793<span class="hljs-keyword">using</span> v8::Isolate;
794<span class="hljs-keyword">using</span> v8::Local;
795<span class="hljs-keyword">using</span> v8::Object;
796<span class="hljs-keyword">using</span> v8::String;
797<span class="hljs-keyword">using</span> v8::Value;
798
799<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyFunction</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
800  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
801  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(String::<span class="hljs-built_in">NewFromUtf8</span>(
802      isolate, <span class="hljs-string">"hello world"</span>).<span class="hljs-built_in">ToLocalChecked</span>());
803}
804
805<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">CreateFunction</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
806  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
807
808  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
809  Local&#x3C;FunctionTemplate> tpl = FunctionTemplate::<span class="hljs-built_in">New</span>(isolate, MyFunction);
810  Local&#x3C;Function> fn = tpl-><span class="hljs-built_in">GetFunction</span>(context).<span class="hljs-built_in">ToLocalChecked</span>();
811
812  <span class="hljs-comment">// omit this to make it anonymous</span>
813  fn-><span class="hljs-built_in">SetName</span>(String::<span class="hljs-built_in">NewFromUtf8</span>(
814      isolate, <span class="hljs-string">"theFunction"</span>).<span class="hljs-built_in">ToLocalChecked</span>());
815
816  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(fn);
817}
818
819<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Init</span><span class="hljs-params">(Local&#x3C;Object> exports, Local&#x3C;Object> <span class="hljs-keyword">module</span>)</span> </span>{
820  <span class="hljs-built_in">NODE_SET_METHOD</span>(<span class="hljs-keyword">module</span>, <span class="hljs-string">"exports"</span>, CreateFunction);
821}
822
823<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, Init)
824
825}  <span class="hljs-comment">// namespace demo</span></code></pre>
826<p>To test:</p>
827<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
828<span class="hljs-keyword">const</span> addon = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
829
830<span class="hljs-keyword">const</span> fn = <span class="hljs-title function_">addon</span>();
831<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-title function_">fn</span>());
832<span class="hljs-comment">// Prints: 'hello world'</span></code></pre>
833<h4>Wrapping C++ objects<span><a class="mark" href="#addons_wrapping_c_objects" id="addons_wrapping_c_objects">#</a></span></h4>
834<p>It is also possible to wrap C++ objects/classes in a way that allows new
835instances to be created using the JavaScript <code>new</code> operator:</p>
836<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
837<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
838<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myobject.h"</span></span>
839
840<span class="hljs-keyword">namespace</span> demo {
841
842<span class="hljs-keyword">using</span> v8::Local;
843<span class="hljs-keyword">using</span> v8::Object;
844
845<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">InitAll</span><span class="hljs-params">(Local&#x3C;Object> exports)</span> </span>{
846  MyObject::<span class="hljs-built_in">Init</span>(exports);
847}
848
849<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, InitAll)
850
851}  <span class="hljs-comment">// namespace demo</span></code></pre>
852<p>Then, in <code>myobject.h</code>, the wrapper class inherits from <code>node::ObjectWrap</code>:</p>
853<pre><code class="language-cpp"><span class="hljs-comment">// myobject.h</span>
854<span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> MYOBJECT_H</span>
855<span class="hljs-meta">#<span class="hljs-keyword">define</span> MYOBJECT_H</span>
856
857<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
858<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node_object_wrap.h></span></span>
859
860<span class="hljs-keyword">namespace</span> demo {
861
862<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyObject</span> : <span class="hljs-keyword">public</span> node::ObjectWrap {
863 <span class="hljs-keyword">public</span>:
864  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">Init</span><span class="hljs-params">(v8::Local&#x3C;v8::Object> exports)</span></span>;
865
866 <span class="hljs-keyword">private</span>:
867  <span class="hljs-function"><span class="hljs-keyword">explicit</span> <span class="hljs-title">MyObject</span><span class="hljs-params">(<span class="hljs-type">double</span> value = <span class="hljs-number">0</span>)</span></span>;
868  ~<span class="hljs-built_in">MyObject</span>();
869
870  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; args)</span></span>;
871  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">PlusOne</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; args)</span></span>;
872
873  <span class="hljs-type">double</span> value_;
874};
875
876}  <span class="hljs-comment">// namespace demo</span>
877
878<span class="hljs-meta">#<span class="hljs-keyword">endif</span></span></code></pre>
879<p>In <code>myobject.cc</code>, implement the various methods that are to be exposed.
880Below, the method <code>plusOne()</code> is exposed by adding it to the constructor's
881prototype:</p>
882<pre><code class="language-cpp"><span class="hljs-comment">// myobject.cc</span>
883<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myobject.h"</span></span>
884
885<span class="hljs-keyword">namespace</span> demo {
886
887<span class="hljs-keyword">using</span> v8::Context;
888<span class="hljs-keyword">using</span> v8::Function;
889<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
890<span class="hljs-keyword">using</span> v8::FunctionTemplate;
891<span class="hljs-keyword">using</span> v8::Isolate;
892<span class="hljs-keyword">using</span> v8::Local;
893<span class="hljs-keyword">using</span> v8::Number;
894<span class="hljs-keyword">using</span> v8::Object;
895<span class="hljs-keyword">using</span> v8::ObjectTemplate;
896<span class="hljs-keyword">using</span> v8::String;
897<span class="hljs-keyword">using</span> v8::Value;
898
899MyObject::<span class="hljs-built_in">MyObject</span>(<span class="hljs-type">double</span> value) : <span class="hljs-built_in">value_</span>(value) {
900}
901
902MyObject::~<span class="hljs-built_in">MyObject</span>() {
903}
904
905<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::Init</span><span class="hljs-params">(Local&#x3C;Object> exports)</span> </span>{
906  Isolate* isolate = exports-><span class="hljs-built_in">GetIsolate</span>();
907  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
908
909  Local&#x3C;ObjectTemplate> addon_data_tpl = ObjectTemplate::<span class="hljs-built_in">New</span>(isolate);
910  addon_data_tpl-><span class="hljs-built_in">SetInternalFieldCount</span>(<span class="hljs-number">1</span>);  <span class="hljs-comment">// 1 field for the MyObject::New()</span>
911  Local&#x3C;Object> addon_data =
912      addon_data_tpl-><span class="hljs-built_in">NewInstance</span>(context).<span class="hljs-built_in">ToLocalChecked</span>();
913
914  <span class="hljs-comment">// Prepare constructor template</span>
915  Local&#x3C;FunctionTemplate> tpl = FunctionTemplate::<span class="hljs-built_in">New</span>(isolate, New, addon_data);
916  tpl-><span class="hljs-built_in">SetClassName</span>(String::<span class="hljs-built_in">NewFromUtf8</span>(isolate, <span class="hljs-string">"MyObject"</span>).<span class="hljs-built_in">ToLocalChecked</span>());
917  tpl-><span class="hljs-built_in">InstanceTemplate</span>()-><span class="hljs-built_in">SetInternalFieldCount</span>(<span class="hljs-number">1</span>);
918
919  <span class="hljs-comment">// Prototype</span>
920  <span class="hljs-built_in">NODE_SET_PROTOTYPE_METHOD</span>(tpl, <span class="hljs-string">"plusOne"</span>, PlusOne);
921
922  Local&#x3C;Function> constructor = tpl-><span class="hljs-built_in">GetFunction</span>(context).<span class="hljs-built_in">ToLocalChecked</span>();
923  addon_data-><span class="hljs-built_in">SetInternalField</span>(<span class="hljs-number">0</span>, constructor);
924  exports-><span class="hljs-built_in">Set</span>(context, String::<span class="hljs-built_in">NewFromUtf8</span>(
925      isolate, <span class="hljs-string">"MyObject"</span>).<span class="hljs-built_in">ToLocalChecked</span>(),
926      constructor).<span class="hljs-built_in">FromJust</span>();
927}
928
929<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
930  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
931  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
932
933  <span class="hljs-keyword">if</span> (args.<span class="hljs-built_in">IsConstructCall</span>()) {
934    <span class="hljs-comment">// Invoked as constructor: `new MyObject(...)`</span>
935    <span class="hljs-type">double</span> value = args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">IsUndefined</span>() ?
936        <span class="hljs-number">0</span> : args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">NumberValue</span>(context).<span class="hljs-built_in">FromMaybe</span>(<span class="hljs-number">0</span>);
937    MyObject* obj = <span class="hljs-keyword">new</span> <span class="hljs-built_in">MyObject</span>(value);
938    obj-><span class="hljs-built_in">Wrap</span>(args.<span class="hljs-built_in">This</span>());
939    args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(args.<span class="hljs-built_in">This</span>());
940  } <span class="hljs-keyword">else</span> {
941    <span class="hljs-comment">// Invoked as plain function `MyObject(...)`, turn into construct call.</span>
942    <span class="hljs-keyword">const</span> <span class="hljs-type">int</span> argc = <span class="hljs-number">1</span>;
943    Local&#x3C;Value> argv[argc] = { args[<span class="hljs-number">0</span>] };
944    Local&#x3C;Function> cons =
945        args.<span class="hljs-built_in">Data</span>().<span class="hljs-built_in">As</span>&#x3C;Object>()-><span class="hljs-built_in">GetInternalField</span>(<span class="hljs-number">0</span>).<span class="hljs-built_in">As</span>&#x3C;Function>();
946    Local&#x3C;Object> result =
947        cons-><span class="hljs-built_in">NewInstance</span>(context, argc, argv).<span class="hljs-built_in">ToLocalChecked</span>();
948    args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(result);
949  }
950}
951
952<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::PlusOne</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
953  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
954
955  MyObject* obj = ObjectWrap::<span class="hljs-built_in">Unwrap</span>&#x3C;MyObject>(args.<span class="hljs-built_in">Holder</span>());
956  obj->value_ += <span class="hljs-number">1</span>;
957
958  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(Number::<span class="hljs-built_in">New</span>(isolate, obj->value_));
959}
960
961}  <span class="hljs-comment">// namespace demo</span></code></pre>
962<p>To build this example, the <code>myobject.cc</code> file must be added to the
963<code>binding.gyp</code>:</p>
964<pre><code class="language-json"><span class="hljs-punctuation">{</span>
965  <span class="hljs-attr">"targets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
966    <span class="hljs-punctuation">{</span>
967      <span class="hljs-attr">"target_name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"addon"</span><span class="hljs-punctuation">,</span>
968      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
969        <span class="hljs-string">"addon.cc"</span><span class="hljs-punctuation">,</span>
970        <span class="hljs-string">"myobject.cc"</span>
971      <span class="hljs-punctuation">]</span>
972    <span class="hljs-punctuation">}</span>
973  <span class="hljs-punctuation">]</span>
974<span class="hljs-punctuation">}</span></code></pre>
975<p>Test it with:</p>
976<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
977<span class="hljs-keyword">const</span> addon = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
978
979<span class="hljs-keyword">const</span> obj = <span class="hljs-keyword">new</span> addon.<span class="hljs-title class_">MyObject</span>(<span class="hljs-number">10</span>);
980<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj.<span class="hljs-title function_">plusOne</span>());
981<span class="hljs-comment">// Prints: 11</span>
982<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj.<span class="hljs-title function_">plusOne</span>());
983<span class="hljs-comment">// Prints: 12</span>
984<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj.<span class="hljs-title function_">plusOne</span>());
985<span class="hljs-comment">// Prints: 13</span></code></pre>
986<p>The destructor for a wrapper object will run when the object is
987garbage-collected. For destructor testing, there are command-line flags that
988can be used to make it possible to force garbage collection. These flags are
989provided by the underlying V8 JavaScript engine. They are subject to change
990or removal at any time. They are not documented by Node.js or V8, and they
991should never be used outside of testing.</p>
992<h4>Factory of wrapped objects<span><a class="mark" href="#addons_factory_of_wrapped_objects" id="addons_factory_of_wrapped_objects">#</a></span></h4>
993<p>Alternatively, it is possible to use a factory pattern to avoid explicitly
994creating object instances using the JavaScript <code>new</code> operator:</p>
995<pre><code class="language-js"><span class="hljs-keyword">const</span> obj = addon.<span class="hljs-title function_">createObject</span>();
996<span class="hljs-comment">// instead of:</span>
997<span class="hljs-comment">// const obj = new addon.Object();</span></code></pre>
998<p>First, the <code>createObject()</code> method is implemented in <code>addon.cc</code>:</p>
999<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
1000<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
1001<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myobject.h"</span></span>
1002
1003<span class="hljs-keyword">namespace</span> demo {
1004
1005<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
1006<span class="hljs-keyword">using</span> v8::Isolate;
1007<span class="hljs-keyword">using</span> v8::Local;
1008<span class="hljs-keyword">using</span> v8::Object;
1009<span class="hljs-keyword">using</span> v8::String;
1010<span class="hljs-keyword">using</span> v8::Value;
1011
1012<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">CreateObject</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1013  MyObject::<span class="hljs-built_in">NewInstance</span>(args);
1014}
1015
1016<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">InitAll</span><span class="hljs-params">(Local&#x3C;Object> exports, Local&#x3C;Object> <span class="hljs-keyword">module</span>)</span> </span>{
1017  MyObject::<span class="hljs-built_in">Init</span>(exports-><span class="hljs-built_in">GetIsolate</span>());
1018
1019  <span class="hljs-built_in">NODE_SET_METHOD</span>(<span class="hljs-keyword">module</span>, <span class="hljs-string">"exports"</span>, CreateObject);
1020}
1021
1022<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, InitAll)
1023
1024}  <span class="hljs-comment">// namespace demo</span></code></pre>
1025<p>In <code>myobject.h</code>, the static method <code>NewInstance()</code> is added to handle
1026instantiating the object. This method takes the place of using <code>new</code> in
1027JavaScript:</p>
1028<pre><code class="language-cpp"><span class="hljs-comment">// myobject.h</span>
1029<span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> MYOBJECT_H</span>
1030<span class="hljs-meta">#<span class="hljs-keyword">define</span> MYOBJECT_H</span>
1031
1032<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
1033<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node_object_wrap.h></span></span>
1034
1035<span class="hljs-keyword">namespace</span> demo {
1036
1037<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyObject</span> : <span class="hljs-keyword">public</span> node::ObjectWrap {
1038 <span class="hljs-keyword">public</span>:
1039  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">Init</span><span class="hljs-params">(v8::Isolate* isolate)</span></span>;
1040  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">NewInstance</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; args)</span></span>;
1041
1042 <span class="hljs-keyword">private</span>:
1043  <span class="hljs-function"><span class="hljs-keyword">explicit</span> <span class="hljs-title">MyObject</span><span class="hljs-params">(<span class="hljs-type">double</span> value = <span class="hljs-number">0</span>)</span></span>;
1044  ~<span class="hljs-built_in">MyObject</span>();
1045
1046  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; args)</span></span>;
1047  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">PlusOne</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; args)</span></span>;
1048  <span class="hljs-keyword">static</span> v8::Global&#x3C;v8::Function> constructor;
1049  <span class="hljs-type">double</span> value_;
1050};
1051
1052}  <span class="hljs-comment">// namespace demo</span>
1053
1054<span class="hljs-meta">#<span class="hljs-keyword">endif</span></span></code></pre>
1055<p>The implementation in <code>myobject.cc</code> is similar to the previous example:</p>
1056<pre><code class="language-cpp"><span class="hljs-comment">// myobject.cc</span>
1057<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
1058<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myobject.h"</span></span>
1059
1060<span class="hljs-keyword">namespace</span> demo {
1061
1062<span class="hljs-keyword">using</span> node::AddEnvironmentCleanupHook;
1063<span class="hljs-keyword">using</span> v8::Context;
1064<span class="hljs-keyword">using</span> v8::Function;
1065<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
1066<span class="hljs-keyword">using</span> v8::FunctionTemplate;
1067<span class="hljs-keyword">using</span> v8::Global;
1068<span class="hljs-keyword">using</span> v8::Isolate;
1069<span class="hljs-keyword">using</span> v8::Local;
1070<span class="hljs-keyword">using</span> v8::Number;
1071<span class="hljs-keyword">using</span> v8::Object;
1072<span class="hljs-keyword">using</span> v8::String;
1073<span class="hljs-keyword">using</span> v8::Value;
1074
1075<span class="hljs-comment">// Warning! This is not thread-safe, this addon cannot be used for worker</span>
1076<span class="hljs-comment">// threads.</span>
1077Global&#x3C;Function> MyObject::constructor;
1078
1079MyObject::<span class="hljs-built_in">MyObject</span>(<span class="hljs-type">double</span> value) : <span class="hljs-built_in">value_</span>(value) {
1080}
1081
1082MyObject::~<span class="hljs-built_in">MyObject</span>() {
1083}
1084
1085<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::Init</span><span class="hljs-params">(Isolate* isolate)</span> </span>{
1086  <span class="hljs-comment">// Prepare constructor template</span>
1087  Local&#x3C;FunctionTemplate> tpl = FunctionTemplate::<span class="hljs-built_in">New</span>(isolate, New);
1088  tpl-><span class="hljs-built_in">SetClassName</span>(String::<span class="hljs-built_in">NewFromUtf8</span>(isolate, <span class="hljs-string">"MyObject"</span>).<span class="hljs-built_in">ToLocalChecked</span>());
1089  tpl-><span class="hljs-built_in">InstanceTemplate</span>()-><span class="hljs-built_in">SetInternalFieldCount</span>(<span class="hljs-number">1</span>);
1090
1091  <span class="hljs-comment">// Prototype</span>
1092  <span class="hljs-built_in">NODE_SET_PROTOTYPE_METHOD</span>(tpl, <span class="hljs-string">"plusOne"</span>, PlusOne);
1093
1094  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
1095  constructor.<span class="hljs-built_in">Reset</span>(isolate, tpl-><span class="hljs-built_in">GetFunction</span>(context).<span class="hljs-built_in">ToLocalChecked</span>());
1096
1097  <span class="hljs-built_in">AddEnvironmentCleanupHook</span>(isolate, [](<span class="hljs-type">void</span>*) {
1098    constructor.<span class="hljs-built_in">Reset</span>();
1099  }, <span class="hljs-literal">nullptr</span>);
1100}
1101
1102<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1103  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
1104  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
1105
1106  <span class="hljs-keyword">if</span> (args.<span class="hljs-built_in">IsConstructCall</span>()) {
1107    <span class="hljs-comment">// Invoked as constructor: `new MyObject(...)`</span>
1108    <span class="hljs-type">double</span> value = args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">IsUndefined</span>() ?
1109        <span class="hljs-number">0</span> : args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">NumberValue</span>(context).<span class="hljs-built_in">FromMaybe</span>(<span class="hljs-number">0</span>);
1110    MyObject* obj = <span class="hljs-keyword">new</span> <span class="hljs-built_in">MyObject</span>(value);
1111    obj-><span class="hljs-built_in">Wrap</span>(args.<span class="hljs-built_in">This</span>());
1112    args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(args.<span class="hljs-built_in">This</span>());
1113  } <span class="hljs-keyword">else</span> {
1114    <span class="hljs-comment">// Invoked as plain function `MyObject(...)`, turn into construct call.</span>
1115    <span class="hljs-keyword">const</span> <span class="hljs-type">int</span> argc = <span class="hljs-number">1</span>;
1116    Local&#x3C;Value> argv[argc] = { args[<span class="hljs-number">0</span>] };
1117    Local&#x3C;Function> cons = Local&#x3C;Function>::<span class="hljs-built_in">New</span>(isolate, constructor);
1118    Local&#x3C;Object> instance =
1119        cons-><span class="hljs-built_in">NewInstance</span>(context, argc, argv).<span class="hljs-built_in">ToLocalChecked</span>();
1120    args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(instance);
1121  }
1122}
1123
1124<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::NewInstance</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1125  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
1126
1127  <span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> argc = <span class="hljs-number">1</span>;
1128  Local&#x3C;Value> argv[argc] = { args[<span class="hljs-number">0</span>] };
1129  Local&#x3C;Function> cons = Local&#x3C;Function>::<span class="hljs-built_in">New</span>(isolate, constructor);
1130  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
1131  Local&#x3C;Object> instance =
1132      cons-><span class="hljs-built_in">NewInstance</span>(context, argc, argv).<span class="hljs-built_in">ToLocalChecked</span>();
1133
1134  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(instance);
1135}
1136
1137<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::PlusOne</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1138  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
1139
1140  MyObject* obj = ObjectWrap::<span class="hljs-built_in">Unwrap</span>&#x3C;MyObject>(args.<span class="hljs-built_in">Holder</span>());
1141  obj->value_ += <span class="hljs-number">1</span>;
1142
1143  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(Number::<span class="hljs-built_in">New</span>(isolate, obj->value_));
1144}
1145
1146}  <span class="hljs-comment">// namespace demo</span></code></pre>
1147<p>Once again, to build this example, the <code>myobject.cc</code> file must be added to the
1148<code>binding.gyp</code>:</p>
1149<pre><code class="language-json"><span class="hljs-punctuation">{</span>
1150  <span class="hljs-attr">"targets"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
1151    <span class="hljs-punctuation">{</span>
1152      <span class="hljs-attr">"target_name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"addon"</span><span class="hljs-punctuation">,</span>
1153      <span class="hljs-attr">"sources"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
1154        <span class="hljs-string">"addon.cc"</span><span class="hljs-punctuation">,</span>
1155        <span class="hljs-string">"myobject.cc"</span>
1156      <span class="hljs-punctuation">]</span>
1157    <span class="hljs-punctuation">}</span>
1158  <span class="hljs-punctuation">]</span>
1159<span class="hljs-punctuation">}</span></code></pre>
1160<p>Test it with:</p>
1161<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
1162<span class="hljs-keyword">const</span> createObject = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
1163
1164<span class="hljs-keyword">const</span> obj = <span class="hljs-title function_">createObject</span>(<span class="hljs-number">10</span>);
1165<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj.<span class="hljs-title function_">plusOne</span>());
1166<span class="hljs-comment">// Prints: 11</span>
1167<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj.<span class="hljs-title function_">plusOne</span>());
1168<span class="hljs-comment">// Prints: 12</span>
1169<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj.<span class="hljs-title function_">plusOne</span>());
1170<span class="hljs-comment">// Prints: 13</span>
1171
1172<span class="hljs-keyword">const</span> obj2 = <span class="hljs-title function_">createObject</span>(<span class="hljs-number">20</span>);
1173<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj2.<span class="hljs-title function_">plusOne</span>());
1174<span class="hljs-comment">// Prints: 21</span>
1175<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj2.<span class="hljs-title function_">plusOne</span>());
1176<span class="hljs-comment">// Prints: 22</span>
1177<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(obj2.<span class="hljs-title function_">plusOne</span>());
1178<span class="hljs-comment">// Prints: 23</span></code></pre>
1179<h4>Passing wrapped objects around<span><a class="mark" href="#addons_passing_wrapped_objects_around" id="addons_passing_wrapped_objects_around">#</a></span></h4>
1180<p>In addition to wrapping and returning C++ objects, it is possible to pass
1181wrapped objects around by unwrapping them with the Node.js helper function
1182<code>node::ObjectWrap::Unwrap</code>. The following examples shows a function <code>add()</code>
1183that can take two <code>MyObject</code> objects as input arguments:</p>
1184<pre><code class="language-cpp"><span class="hljs-comment">// addon.cc</span>
1185<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
1186<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node_object_wrap.h></span></span>
1187<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myobject.h"</span></span>
1188
1189<span class="hljs-keyword">namespace</span> demo {
1190
1191<span class="hljs-keyword">using</span> v8::Context;
1192<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
1193<span class="hljs-keyword">using</span> v8::Isolate;
1194<span class="hljs-keyword">using</span> v8::Local;
1195<span class="hljs-keyword">using</span> v8::Number;
1196<span class="hljs-keyword">using</span> v8::Object;
1197<span class="hljs-keyword">using</span> v8::String;
1198<span class="hljs-keyword">using</span> v8::Value;
1199
1200<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">CreateObject</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1201  MyObject::<span class="hljs-built_in">NewInstance</span>(args);
1202}
1203
1204<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Add</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1205  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
1206  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
1207
1208  MyObject* obj1 = node::ObjectWrap::<span class="hljs-built_in">Unwrap</span>&#x3C;MyObject>(
1209      args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">ToObject</span>(context).<span class="hljs-built_in">ToLocalChecked</span>());
1210  MyObject* obj2 = node::ObjectWrap::<span class="hljs-built_in">Unwrap</span>&#x3C;MyObject>(
1211      args[<span class="hljs-number">1</span>]-><span class="hljs-built_in">ToObject</span>(context).<span class="hljs-built_in">ToLocalChecked</span>());
1212
1213  <span class="hljs-type">double</span> sum = obj1-><span class="hljs-built_in">value</span>() + obj2-><span class="hljs-built_in">value</span>();
1214  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(Number::<span class="hljs-built_in">New</span>(isolate, sum));
1215}
1216
1217<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">InitAll</span><span class="hljs-params">(Local&#x3C;Object> exports)</span> </span>{
1218  MyObject::<span class="hljs-built_in">Init</span>(exports-><span class="hljs-built_in">GetIsolate</span>());
1219
1220  <span class="hljs-built_in">NODE_SET_METHOD</span>(exports, <span class="hljs-string">"createObject"</span>, CreateObject);
1221  <span class="hljs-built_in">NODE_SET_METHOD</span>(exports, <span class="hljs-string">"add"</span>, Add);
1222}
1223
1224<span class="hljs-built_in">NODE_MODULE</span>(NODE_GYP_MODULE_NAME, InitAll)
1225
1226}  <span class="hljs-comment">// namespace demo</span></code></pre>
1227<p>In <code>myobject.h</code>, a new public method is added to allow access to private values
1228after unwrapping the object.</p>
1229<pre><code class="language-cpp"><span class="hljs-comment">// myobject.h</span>
1230<span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> MYOBJECT_H</span>
1231<span class="hljs-meta">#<span class="hljs-keyword">define</span> MYOBJECT_H</span>
1232
1233<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
1234<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node_object_wrap.h></span></span>
1235
1236<span class="hljs-keyword">namespace</span> demo {
1237
1238<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyObject</span> : <span class="hljs-keyword">public</span> node::ObjectWrap {
1239 <span class="hljs-keyword">public</span>:
1240  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">Init</span><span class="hljs-params">(v8::Isolate* isolate)</span></span>;
1241  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">NewInstance</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; args)</span></span>;
1242  <span class="hljs-function"><span class="hljs-keyword">inline</span> <span class="hljs-type">double</span> <span class="hljs-title">value</span><span class="hljs-params">()</span> <span class="hljs-keyword">const</span> </span>{ <span class="hljs-keyword">return</span> value_; }
1243
1244 <span class="hljs-keyword">private</span>:
1245  <span class="hljs-function"><span class="hljs-keyword">explicit</span> <span class="hljs-title">MyObject</span><span class="hljs-params">(<span class="hljs-type">double</span> value = <span class="hljs-number">0</span>)</span></span>;
1246  ~<span class="hljs-built_in">MyObject</span>();
1247
1248  <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-type">void</span> <span class="hljs-title">New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> v8::FunctionCallbackInfo&#x3C;v8::Value>&#x26; args)</span></span>;
1249  <span class="hljs-keyword">static</span> v8::Global&#x3C;v8::Function> constructor;
1250  <span class="hljs-type">double</span> value_;
1251};
1252
1253}  <span class="hljs-comment">// namespace demo</span>
1254
1255<span class="hljs-meta">#<span class="hljs-keyword">endif</span></span></code></pre>
1256<p>The implementation of <code>myobject.cc</code> is similar to before:</p>
1257<pre><code class="language-cpp"><span class="hljs-comment">// myobject.cc</span>
1258<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&#x3C;node.h></span></span>
1259<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myobject.h"</span></span>
1260
1261<span class="hljs-keyword">namespace</span> demo {
1262
1263<span class="hljs-keyword">using</span> node::AddEnvironmentCleanupHook;
1264<span class="hljs-keyword">using</span> v8::Context;
1265<span class="hljs-keyword">using</span> v8::Function;
1266<span class="hljs-keyword">using</span> v8::FunctionCallbackInfo;
1267<span class="hljs-keyword">using</span> v8::FunctionTemplate;
1268<span class="hljs-keyword">using</span> v8::Global;
1269<span class="hljs-keyword">using</span> v8::Isolate;
1270<span class="hljs-keyword">using</span> v8::Local;
1271<span class="hljs-keyword">using</span> v8::Object;
1272<span class="hljs-keyword">using</span> v8::String;
1273<span class="hljs-keyword">using</span> v8::Value;
1274
1275<span class="hljs-comment">// Warning! This is not thread-safe, this addon cannot be used for worker</span>
1276<span class="hljs-comment">// threads.</span>
1277Global&#x3C;Function> MyObject::constructor;
1278
1279MyObject::<span class="hljs-built_in">MyObject</span>(<span class="hljs-type">double</span> value) : <span class="hljs-built_in">value_</span>(value) {
1280}
1281
1282MyObject::~<span class="hljs-built_in">MyObject</span>() {
1283}
1284
1285<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::Init</span><span class="hljs-params">(Isolate* isolate)</span> </span>{
1286  <span class="hljs-comment">// Prepare constructor template</span>
1287  Local&#x3C;FunctionTemplate> tpl = FunctionTemplate::<span class="hljs-built_in">New</span>(isolate, New);
1288  tpl-><span class="hljs-built_in">SetClassName</span>(String::<span class="hljs-built_in">NewFromUtf8</span>(isolate, <span class="hljs-string">"MyObject"</span>).<span class="hljs-built_in">ToLocalChecked</span>());
1289  tpl-><span class="hljs-built_in">InstanceTemplate</span>()-><span class="hljs-built_in">SetInternalFieldCount</span>(<span class="hljs-number">1</span>);
1290
1291  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
1292  constructor.<span class="hljs-built_in">Reset</span>(isolate, tpl-><span class="hljs-built_in">GetFunction</span>(context).<span class="hljs-built_in">ToLocalChecked</span>());
1293
1294  <span class="hljs-built_in">AddEnvironmentCleanupHook</span>(isolate, [](<span class="hljs-type">void</span>*) {
1295    constructor.<span class="hljs-built_in">Reset</span>();
1296  }, <span class="hljs-literal">nullptr</span>);
1297}
1298
1299<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1300  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
1301  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
1302
1303  <span class="hljs-keyword">if</span> (args.<span class="hljs-built_in">IsConstructCall</span>()) {
1304    <span class="hljs-comment">// Invoked as constructor: `new MyObject(...)`</span>
1305    <span class="hljs-type">double</span> value = args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">IsUndefined</span>() ?
1306        <span class="hljs-number">0</span> : args[<span class="hljs-number">0</span>]-><span class="hljs-built_in">NumberValue</span>(context).<span class="hljs-built_in">FromMaybe</span>(<span class="hljs-number">0</span>);
1307    MyObject* obj = <span class="hljs-keyword">new</span> <span class="hljs-built_in">MyObject</span>(value);
1308    obj-><span class="hljs-built_in">Wrap</span>(args.<span class="hljs-built_in">This</span>());
1309    args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(args.<span class="hljs-built_in">This</span>());
1310  } <span class="hljs-keyword">else</span> {
1311    <span class="hljs-comment">// Invoked as plain function `MyObject(...)`, turn into construct call.</span>
1312    <span class="hljs-keyword">const</span> <span class="hljs-type">int</span> argc = <span class="hljs-number">1</span>;
1313    Local&#x3C;Value> argv[argc] = { args[<span class="hljs-number">0</span>] };
1314    Local&#x3C;Function> cons = Local&#x3C;Function>::<span class="hljs-built_in">New</span>(isolate, constructor);
1315    Local&#x3C;Object> instance =
1316        cons-><span class="hljs-built_in">NewInstance</span>(context, argc, argv).<span class="hljs-built_in">ToLocalChecked</span>();
1317    args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(instance);
1318  }
1319}
1320
1321<span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">MyObject::NewInstance</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&#x3C;Value>&#x26; args)</span> </span>{
1322  Isolate* isolate = args.<span class="hljs-built_in">GetIsolate</span>();
1323
1324  <span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> argc = <span class="hljs-number">1</span>;
1325  Local&#x3C;Value> argv[argc] = { args[<span class="hljs-number">0</span>] };
1326  Local&#x3C;Function> cons = Local&#x3C;Function>::<span class="hljs-built_in">New</span>(isolate, constructor);
1327  Local&#x3C;Context> context = isolate-><span class="hljs-built_in">GetCurrentContext</span>();
1328  Local&#x3C;Object> instance =
1329      cons-><span class="hljs-built_in">NewInstance</span>(context, argc, argv).<span class="hljs-built_in">ToLocalChecked</span>();
1330
1331  args.<span class="hljs-built_in">GetReturnValue</span>().<span class="hljs-built_in">Set</span>(instance);
1332}
1333
1334}  <span class="hljs-comment">// namespace demo</span></code></pre>
1335<p>Test it with:</p>
1336<pre><code class="language-js"><span class="hljs-comment">// test.js</span>
1337<span class="hljs-keyword">const</span> addon = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./build/Release/addon'</span>);
1338
1339<span class="hljs-keyword">const</span> obj1 = addon.<span class="hljs-title function_">createObject</span>(<span class="hljs-number">10</span>);
1340<span class="hljs-keyword">const</span> obj2 = addon.<span class="hljs-title function_">createObject</span>(<span class="hljs-number">20</span>);
1341<span class="hljs-keyword">const</span> result = addon.<span class="hljs-title function_">add</span>(obj1, obj2);
1342
1343<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(result);
1344<span class="hljs-comment">// Prints: 30</span></code></pre></section>
1345        <!-- API END -->
1346      </div>
1347    </div>
1348  </div>
1349  <script>
1350    'use strict';
1351    {
1352      const kCustomPreference = 'customDarkTheme';
1353      const userSettings = sessionStorage.getItem(kCustomPreference);
1354      const themeToggleButton = document.getElementById('theme-toggle-btn');
1355      if (userSettings === null && window.matchMedia) {
1356        const mq = window.matchMedia('(prefers-color-scheme: dark)');
1357        if ('onchange' in mq) {
1358          function mqChangeListener(e) {
1359            document.body.classList.toggle('dark-mode', e.matches);
1360          }
1361          mq.addEventListener('change', mqChangeListener);
1362          if (themeToggleButton) {
1363            themeToggleButton.addEventListener('click', function() {
1364              mq.removeEventListener('change', mqChangeListener);
1365            }, { once: true });
1366          }
1367        }
1368        if (mq.matches) {
1369          document.body.classList.add('dark-mode');
1370        }
1371      } else if (userSettings === 'true') {
1372        document.body.classList.add('dark-mode');
1373      }
1374      if (themeToggleButton) {
1375        themeToggleButton.hidden = false;
1376        themeToggleButton.addEventListener('click', function() {
1377          sessionStorage.setItem(
1378            kCustomPreference,
1379            document.body.classList.toggle('dark-mode')
1380          );
1381        });
1382      }
1383    }
1384  </script>
1385</body>
1386</html>
1387