napi-derive
Checkout more examples in examples folder
extern crate napi_derive;
use *;
Symbol-keyed class members
Use symbol_for on a class method, getter, setter, or public field to expose it
under Symbol.for(name) instead of a string property name:
JavaScript can read it as chunk[Symbol.for('_runtime')]. Use the same
symbol_for on a getter and setter to define a single accessor; they share one
descriptor only when they are in the same #[napi] impl block. Static methods
and factories are also supported. Names are used verbatim, without case conversion.
symbol_for cannot be combined with js_name or a named getter/setter.
Constructors, top-level exports, and fields of object, array, or transparent
structs and structured enums do not support symbol_for.
These members are omitted from generated TypeScript declarations, including when
ts_return_type is supplied. Positional arguments of a generated constructor are
retained. Internal TypeScript callers can declare their own symbol-keyed types.
Symbol properties are skipped by string-key enumeration (Object.keys, for...in,
Object.getOwnPropertyNames) and JSON serialization. They are not private:
Object.getOwnPropertySymbols and Reflect.ownKeys reveal them, and anyone knowing
the registry key can access them with Symbol.for. Property attributes such as
enumerable, writable, configurable, and readonly retain their usual meaning.
For class members, inspect the class prototype (or constructor for static methods).
symbol_for requires enabling the napi9 feature (or a higher Node-API feature)
on the napi dependency. With a lower Node-API configuration it fails to compile
with "symbol_for requires the napi9 feature of the napi crate". Symbols are
resolved with node_api_symbol_for in each Node environment during class
registration; there is no JavaScript fallback.
Well-known symbol class members
Use well_known_symbol to key a class method, getter, setter, or public field by
one of JavaScript's well-known symbols. The value is the bare name, without the
Symbol. prefix:
The accepted names are asyncDispose, asyncIterator, dispose, hasInstance,
isConcatSpreadable, iterator, match, matchAll, replace, search,
species, split, toPrimitive, toStringTag, and unscopables; any other
value fails to compile. The placement rules are the same as for symbol_for:
a getter and setter with the same name share one accessor when they are in the
same #[napi] impl block, static methods and factories are supported (except
for hasInstance, see below), and
well_known_symbol cannot be combined with js_name, symbol_for, or a named
getter/setter, nor used on constructors, top-level exports, or fields of
object, array, or transparent structs and structured enums.
Unlike symbol_for, these members are declared in the generated TypeScript with
computed keys, for example get [globalThis.Symbol.toStringTag](): string and
static [globalThis.Symbol.toPrimitive](hint: string): string. The keys go
through globalThis, so an export named Symbol does not shadow them. The
consuming project needs a TypeScript lib that declares the symbol (for example
esnext.disposable for dispose and asyncDispose).
No Node-API feature is required. The symbol is read from globalThis.Symbol in
each environment during class registration. If it is not a symbol there, the
registration fails with "Symbol.dispose is not available in this runtime" (for
dispose) rather than defining the member under another key, so the addon fails
to load.
hasInstance is not accepted on static methods and factories. A static
Symbol.hasInstance replaces instanceof for the class, and napi-rs uses
instanceof itself for strict argument validation, Either dispatch, and
instance_of.
Do not use well_known_symbol = "iterator" on a class with #[napi(iterator)],
or "asyncIterator" on one with #[napi(async_iterator)]: those features set
the same symbol as an own property of every instance, which shadows the class
member.