From 485befffcbb55eecec68605d356efde2773f6c86 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sun, 6 Jul 2025 21:43:35 -0700 Subject: [PATCH] chore(example): add define_class example (#2765) --- .../__tests__/__snapshots__/values.spec.ts.md | 7 ++++ .../__snapshots__/values.spec.ts.snap | Bin 7264 -> 7302 bytes examples/napi/__tests__/values.spec.ts | 7 ++++ examples/napi/example.wasi-browser.js | 1 + examples/napi/example.wasi.cjs | 24 ++++++++++++++ examples/napi/index.cjs | 1 + examples/napi/index.d.cts | 7 ++++ examples/napi/src/class.rs | 31 ++++++++++++++++-- 8 files changed, 76 insertions(+), 2 deletions(-) diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.md b/examples/napi/__tests__/__snapshots__/values.spec.ts.md index 2c63c527..99390a10 100644 --- a/examples/napi/__tests__/__snapshots__/values.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/values.spec.ts.md @@ -577,6 +577,13 @@ Generated by [AVA](https://avajs.dev). optionalStringField?: string␊ }␊ ␊ + export declare function defineClass(): typeof DynamicRustClass␊ + ␊ + class DynamicRustClass {␊ + constructor(value: number)␊ + rustMethod(): number␊ + }␊ + ␊ export declare function derefUint8Array(a: Uint8Array, b: Uint8ClampedArray): number␊ ␊ export declare function either3(input: string | number | boolean): number␊ diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap index 4e9b2858ac0fc7aa050f920ccd34203067637358..b1e8a99dfa9043f0707d85633f58ecf791afa9c8 100644 GIT binary patch delta 6943 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 z z6tb{r>N1xr%J9Ys<*deB-)LLWVZ)-GCF>cqiyxpQN4X~)JEYUug;v&1&u}T8Y52p`sS5->h?N}V>DoOg^QRi4pPdcZ7_T`*xDTN zT|T9JDH&6UF&9K{3ol!3-q1l5{(s&&k=3oWqMlN(>kjCoD#z<2uhLf&k;yHT3PX8< zVOLowb;!}?nuKZ%2;%|v3gf9Mttxf2O*(U+^Xhg*a!O&9(_yP0iIEo~4HWT>Xhwjd zO`@AOFdJc!tE4!|qJV|#kRrQ|PT_?!z`!SM{q$G|*es%2IcjlI=gAHb4#fDINkX95!S2Tv#!sXQ{&9mpe0>QGaB zVV-s?XM7}PRlH222l{X*-6b+P0SjsM92eY=nRFuZMwD#PkvSJeHEy_o01+LP2TQ$3TadY1p6W15gt-8D!=QpV zjY0>Hpvqq%spo%z=P~yqRP*BPJ}WF5pF$&K@)+7s{cUpuO?_>Um@3m)iLD<69Dgy3H=wcLyY0TU@hNj%e}jG;z%0HGs6rb1R0nhQK&J>#9ebIn*Tef(jN=DsAPNuw z1pQiuu}jnQmH}4Iv47D#l{^Cwq9XcMxA6kHRHDV}qq{sz6quK2Qowb|J2=>)*ssCGjD$3{c0Jo4A+GtZa}5xB>>U2RHrtRl#_3+-_^CczE&Az{cx-Wq?#YUOL!d)%poS-%oY`O# zKwKjT-1D|phawq zya?LLuF(0~u`1w+U8W24RX<|&Dn3G`t{rJ}gJISY+ih`sN3LN!g5*cxAF_Q~Tgs=@ zLiN7HW;GY+e1G)kUlJ*`ym-v$_HjEC^Cp*=WI7}7GSS6P1V+3DU=q)m%v3@RQ^nI* zyzJ7&M}NuXzUqCEnolaKq2*81&qJiM9MTGF?)UDDJQ&iupK66S4qK++)iXv?(feDG zX&MzL>>0m|*WC1siZk|BI`SWtrtBF%trw${dQ26%!koR-9fM5?8+u#;ktZy6?6tb1 zFp4YXj=EAQdElFZ=gzhkph)=f@^f%5>ki_g)qkU|-B>-9?MxZ&#<7Dkv6anvjgOq_ys!1h#_Xg5TD(OlLxbvVPxhfQ zbbs5ksLu8s^So$*`rDXntZvq+16o3I6%{H51zakaWayD`!@PQ?2OV-}25vLofMOr^bvi%~R|<>Ha_ zS=}khNG5#_ueVLoO|2cWXJi<~$U-eAA3A?5Zg&i?P{j^>7q6o$%E0Pbg3l=Jm}-yc zq0LIchPX5+RX|}l-9588kyvjTBRH5pO-OA+)y2grlYtu(f4@>SOr+a*M{~_J<%NJB z{k)cd>7)3B!O!twLRTbE=9+?%B|q0S^S?qNq2+INO33(^JF_Iwq~Uvq&zLYT z#%GhOmjt`C0J~Xc@sH3b_~j5XP(Z{{aA-N+ghh006(eg$Dot delta 6862 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 { ) }) +test('define class', (t) => { + const DynamicRustClass = defineClass() + const instance = new DynamicRustClass(42) + t.is(instance.rustMethod(), 42) +}) + test('async self in class', async (t) => { const b = new Bird('foo') t.is(await b.getNameAsync(), 'foo') diff --git a/examples/napi/example.wasi-browser.js b/examples/napi/example.wasi-browser.js index eea1c018..a5e3b467 100644 --- a/examples/napi/example.wasi-browser.js +++ b/examples/napi/example.wasi-browser.js @@ -206,6 +206,7 @@ export const customStatusCode = __napiModule.exports.customStatusCode export const CustomStringEnum = __napiModule.exports.CustomStringEnum export const dateToNumber = __napiModule.exports.dateToNumber export const DEFAULT_COST = __napiModule.exports.DEFAULT_COST +export const defineClass = __napiModule.exports.defineClass export const derefUint8Array = __napiModule.exports.derefUint8Array export const either3 = __napiModule.exports.either3 export const either4 = __napiModule.exports.either4 diff --git a/examples/napi/example.wasi.cjs b/examples/napi/example.wasi.cjs index f572dc17..b9dedfdf 100644 --- a/examples/napi/example.wasi.cjs +++ b/examples/napi/example.wasi.cjs @@ -65,6 +65,29 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule worker.onmessage = ({ data }) => { __wasmCreateOnMessageForFsProxy(__nodeFs)(data) } + + // The main thread of Node.js waits for all the active handles before exiting. + // But Rust threads are never waited without `thread::join`. + // So here we hack the code of Node.js to prevent the workers from being referenced (active). + // According to https://github.com/nodejs/node/blob/19e0d472728c79d418b74bddff588bea70a403d0/lib/internal/worker.js#L415, + // a worker is consist of two handles: kPublicPort and kHandle. + { + const kPublicPort = Object.getOwnPropertySymbols(worker).find(s => + s.toString().includes("kPublicPort") + ); + if (kPublicPort) { + worker[kPublicPort].ref = () => {}; + } + + const kHandle = Object.getOwnPropertySymbols(worker).find(s => + s.toString().includes("kHandle") + ); + if (kPublicPort) { + worker[kHandle].ref = () => {}; + } + + worker.unref(); + } return worker }, overwriteImports(importObject) { @@ -230,6 +253,7 @@ module.exports.customStatusCode = __napiModule.exports.customStatusCode module.exports.CustomStringEnum = __napiModule.exports.CustomStringEnum module.exports.dateToNumber = __napiModule.exports.dateToNumber module.exports.DEFAULT_COST = __napiModule.exports.DEFAULT_COST +module.exports.defineClass = __napiModule.exports.defineClass module.exports.derefUint8Array = __napiModule.exports.derefUint8Array module.exports.either3 = __napiModule.exports.either3 module.exports.either4 = __napiModule.exports.either4 diff --git a/examples/napi/index.cjs b/examples/napi/index.cjs index 044f4c79..7b4fda0f 100644 --- a/examples/napi/index.cjs +++ b/examples/napi/index.cjs @@ -521,6 +521,7 @@ module.exports.customStatusCode = nativeBinding.customStatusCode module.exports.CustomStringEnum = nativeBinding.CustomStringEnum module.exports.dateToNumber = nativeBinding.dateToNumber module.exports.DEFAULT_COST = nativeBinding.DEFAULT_COST +module.exports.defineClass = nativeBinding.defineClass module.exports.derefUint8Array = nativeBinding.derefUint8Array module.exports.either3 = nativeBinding.either3 module.exports.either4 = nativeBinding.either4 diff --git a/examples/napi/index.d.cts b/examples/napi/index.d.cts index ff4186a4..36a1bafd 100644 --- a/examples/napi/index.d.cts +++ b/examples/napi/index.d.cts @@ -539,6 +539,13 @@ export interface DefaultUseNullableStruct { optionalStringField?: string } +export declare function defineClass(): typeof DynamicRustClass + +class DynamicRustClass { + constructor(value: number) + rustMethod(): number +} + export declare function derefUint8Array(a: Uint8Array, b: Uint8ClampedArray): number export declare function either3(input: string | number | boolean): number diff --git a/examples/napi/src/class.rs b/examples/napi/src/class.rs index 1d7bc29e..8bad11d5 100644 --- a/examples/napi/src/class.rs +++ b/examples/napi/src/class.rs @@ -1,7 +1,7 @@ use napi::{ bindgen_prelude::{ - Buffer, ClassInstance, JavaScriptClassExt, JsObjectValue, JsValue, ObjectFinalize, This, - Uint8Array, Unknown, + Buffer, ClassInstance, Function, JavaScriptClassExt, JsObjectValue, JsValue, ObjectFinalize, + This, Uint8Array, Unknown, }, Env, Property, PropertyAttributes, Result, }; @@ -561,3 +561,30 @@ impl ThingList { Thing } } + +#[napi( + ts_return_type = r#"typeof DynamicRustClass\n\nclass DynamicRustClass { + constructor(value: number) + rustMethod(): number +}"# +)] +pub fn define_class(env: &Env) -> Result { + env.define_class( + "DynamicRustClass", + rust_class_constructor_c_callback, + &[Property::new() + .with_utf8_name("rustMethod")? + .with_method(rust_class_method_c_callback)], + ) +} + +#[napi(no_export)] +fn rust_class_constructor(value: i32, mut this: This) -> Result<()> { + this.set_named_property("dynamicValue", value)?; + Ok(()) +} + +#[napi(no_export)] +fn rust_class_method(this: This) -> Result { + this.get_named_property_unchecked::("dynamicValue") +}