mirror of
https://github.com/napi-rs/napi-rs.git
synced 2025-12-08 19:56:07 +00:00
test(napi): add fixture for re-export complex class (#2733)
This commit is contained in:
parent
1486b1f174
commit
3dce1533fd
@ -3,4 +3,9 @@
|
||||
# https://github.com/rust-lang/rust/issues/134820
|
||||
# pthread_key_create() destructors and segfault after a DSO unloading
|
||||
[target.'cfg(any(all(target_env = "gnu", not(target_os = "windows")), target_os = "freebsd"))']
|
||||
rustflags = ["-C", "link-args=-Wl,-z,nodelete"]
|
||||
rustflags = [
|
||||
"-C",
|
||||
"link-args=-Wl,--warn-unresolved-symbols",
|
||||
"-C",
|
||||
"link-args=-Wl,-z,nodelete",
|
||||
]
|
||||
|
||||
2
.github/workflows/test-release.yaml
vendored
2
.github/workflows/test-release.yaml
vendored
@ -91,7 +91,7 @@ jobs:
|
||||
yarn test:cli
|
||||
yarn test
|
||||
yarn tsc -p examples/napi/tsconfig.json --noEmit --skipLibCheck
|
||||
yarn test:macro
|
||||
RUSTFLAGS="-C link-args=-Wl,-undefined,dynamic_lookup,-no_fixup_chains" yarn test:macro
|
||||
toolchain: stable
|
||||
- host: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
|
||||
@ -1,6 +1,75 @@
|
||||
use napi::{bindgen_prelude::ClassInstance, Either};
|
||||
use napi_derive::napi;
|
||||
|
||||
#[napi(object)]
|
||||
pub struct Shared {
|
||||
pub value: u32,
|
||||
}
|
||||
|
||||
// Test fixture for GitHub issue #2722: Complex struct with constructor and multiple methods
|
||||
#[napi]
|
||||
pub struct ComplexClass {
|
||||
pub value: String,
|
||||
pub number: i32,
|
||||
}
|
||||
|
||||
impl From<(String, i32)> for ComplexClass {
|
||||
fn from(value: (String, i32)) -> Self {
|
||||
ComplexClass {
|
||||
value: value.0,
|
||||
number: value.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> From<Either<ClassInstance<'env, ComplexClass>, String>> for ComplexClass {
|
||||
fn from(value: Either<ClassInstance<'env, ComplexClass>, String>) -> Self {
|
||||
match value {
|
||||
Either::A(instance) => ComplexClass {
|
||||
value: (&*instance).value.clone(),
|
||||
number: instance.number,
|
||||
},
|
||||
Either::B(value) => ComplexClass { value, number: 0 },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl ComplexClass {
|
||||
#[napi(constructor)]
|
||||
pub fn new(value: Either<String, ClassInstance<ComplexClass>>, number: i32) -> Self {
|
||||
let value_str = match value {
|
||||
Either::A(s) => s,
|
||||
Either::B(instance) => format!("cloned:{}", (&*instance).value),
|
||||
};
|
||||
ComplexClass {
|
||||
value: value_str,
|
||||
number,
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn method_one(&self) -> String {
|
||||
format!("method_one: {}", self.value)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn method_two(&self) -> i32 {
|
||||
self.number * 2
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn method_three(&self) -> String {
|
||||
format!("method_three: {} - {}", self.value, self.number)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn method_four(&self) -> bool {
|
||||
self.number > 0
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn method_five(&self) -> String {
|
||||
self.value.to_uppercase()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1050,6 +1050,17 @@ Generated by [AVA](https://avajs.dev).
|
||||
export function xxh128(input: Buffer): bigint␊
|
||||
export function xxh3_64(input: Buffer): bigint␊
|
||||
}␊
|
||||
export declare class ComplexClass {␊
|
||||
value: string␊
|
||||
number: number␊
|
||||
constructor(value: string | ComplexClass, number: number)␊
|
||||
methodOne(): string␊
|
||||
methodTwo(): number␊
|
||||
methodThree(): string␊
|
||||
methodFour(): boolean␊
|
||||
methodFive(): string␊
|
||||
}␊
|
||||
␊
|
||||
export interface Shared {␊
|
||||
value: number␊
|
||||
}␊
|
||||
|
||||
Binary file not shown.
@ -243,6 +243,7 @@ import {
|
||||
JSOnlyMethodsClass,
|
||||
RustOnlyMethodsClass,
|
||||
OriginalRustNameForJsNamedStruct,
|
||||
ComplexClass,
|
||||
} from '../index.cjs'
|
||||
// import other stuff in `#[napi(module_exports)]`
|
||||
import nativeAddon from '../index.cjs'
|
||||
@ -1841,3 +1842,45 @@ test('escapable handle scope', (t) => {
|
||||
shorterEscapableScope(makeIterFunction())
|
||||
})
|
||||
})
|
||||
|
||||
test('complex class with multiple methods - issue #2722', (t) => {
|
||||
// Test creating instance of re-exported class with constructor (Either<String, ClassInstance<ComplexClass>>)
|
||||
t.notThrows(() => {
|
||||
const complex = new ComplexClass('test_value', 42)
|
||||
|
||||
// Test that constructor worked
|
||||
t.is(complex.value, 'test_value')
|
||||
t.is(complex.number, 42)
|
||||
|
||||
// Test all methods work
|
||||
t.is(complex.methodOne(), 'method_one: test_value')
|
||||
t.is(complex.methodTwo(), 84)
|
||||
t.is(complex.methodThree(), 'method_three: test_value - 42')
|
||||
t.is(complex.methodFour(), true)
|
||||
t.is(complex.methodFive(), 'TEST_VALUE')
|
||||
})
|
||||
|
||||
// Test with Either::B variant (ClassInstance instead of string)
|
||||
t.notThrows(() => {
|
||||
const original = new ComplexClass('original', 100)
|
||||
const complex2 = new ComplexClass(original, -10)
|
||||
t.is(complex2.value, 'cloned:original') // Should clone the value
|
||||
t.is(complex2.methodFour(), false)
|
||||
})
|
||||
|
||||
// Test that we can create multiple instances (stress test with Either)
|
||||
t.notThrows(() => {
|
||||
const baseInstance = new ComplexClass('base', 999)
|
||||
for (let i = 0; i < 10; i++) {
|
||||
// Alternate between string and ClassInstance for Either parameter
|
||||
const instance =
|
||||
i % 2 === 0
|
||||
? new ComplexClass(`test${i}`, i)
|
||||
: new ComplexClass(baseInstance, i)
|
||||
|
||||
const expectedValue = i % 2 === 0 ? `test${i}` : 'cloned:base'
|
||||
t.is(instance.value, expectedValue)
|
||||
t.is(instance.number, i)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@ -365,3 +365,4 @@ export const withoutAbortController = __napiModule.exports.withoutAbortControlle
|
||||
export const xxh64Alias = __napiModule.exports.xxh64Alias
|
||||
export const xxh2 = __napiModule.exports.xxh2
|
||||
export const xxh3 = __napiModule.exports.xxh3
|
||||
export const ComplexClass = __napiModule.exports.ComplexClass
|
||||
|
||||
@ -389,3 +389,4 @@ module.exports.withoutAbortController = __napiModule.exports.withoutAbortControl
|
||||
module.exports.xxh64Alias = __napiModule.exports.xxh64Alias
|
||||
module.exports.xxh2 = __napiModule.exports.xxh2
|
||||
module.exports.xxh3 = __napiModule.exports.xxh3
|
||||
module.exports.ComplexClass = __napiModule.exports.ComplexClass
|
||||
|
||||
@ -680,3 +680,4 @@ module.exports.withoutAbortController = nativeBinding.withoutAbortController
|
||||
module.exports.xxh64Alias = nativeBinding.xxh64Alias
|
||||
module.exports.xxh2 = nativeBinding.xxh2
|
||||
module.exports.xxh3 = nativeBinding.xxh3
|
||||
module.exports.ComplexClass = nativeBinding.ComplexClass
|
||||
|
||||
@ -1012,6 +1012,17 @@ export declare namespace xxh3 {
|
||||
export function xxh128(input: Buffer): bigint
|
||||
export function xxh3_64(input: Buffer): bigint
|
||||
}
|
||||
export declare class ComplexClass {
|
||||
value: string
|
||||
number: number
|
||||
constructor(value: string | ComplexClass, number: number)
|
||||
methodOne(): string
|
||||
methodTwo(): number
|
||||
methodThree(): string
|
||||
methodFour(): boolean
|
||||
methodFive(): string
|
||||
}
|
||||
|
||||
export interface Shared {
|
||||
value: number
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use napi::bindgen_prelude::create_custom_tokio_runtime;
|
||||
use napi::bindgen_prelude::{JsObjectValue, Object, Result, Symbol};
|
||||
pub use napi_shared::*;
|
||||
|
||||
#[macro_use]
|
||||
extern crate napi_derive;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user