fix(napi): add back the typecheck logic that was accidentally removed in Object::get_named_property (#1982)

- Close https://github.com/napi-rs/napi-rs/issues/1641
This commit is contained in:
LongYinan 2024-02-28 14:29:02 +08:00 committed by GitHub
parent 95dd6ef485
commit aeb0b4766d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 50 additions and 1 deletions

View file

@ -347,7 +347,7 @@ macro_rules! impl_object_methods {
pub fn get_named_property<T>(&self, name: &str) -> Result<T>
where
T: FromNapiValue,
T: FromNapiValue + ValidateNapiValue,
{
let key = CString::new(name)?;
let mut raw_value = ptr::null_mut();
@ -357,6 +357,12 @@ macro_rules! impl_object_methods {
},
"get_named_property error"
)?;
unsafe { <T as ValidateNapiValue>::validate(self.0.env, raw_value) }.map_err(
|mut err| {
err.reason = format!("Object property '{name}' type mismatch. {}", err.reason);
err
},
)?;
unsafe { <T as FromNapiValue>::from_napi_value(self.0.env, raw_value) }
}

View file

@ -515,6 +515,8 @@ Generated by [AVA](https://avajs.dev).
bird: Bird␊
}␊
export function objectGetNamedPropertyShouldPerformTypecheck(obj: { foo: number; bar: string; }): void␊
export interface ObjectOnlyFromJs {␊
count: number␊
callback: (err: Error | null, arg: number) => any␊

View file

@ -105,6 +105,7 @@ import {
createExternalTypedArray,
mutateTypedArray,
receiveAllOptionalObject,
objectGetNamedPropertyShouldPerformTypecheck,
fnReceivedAliased,
ALIAS,
appendBuffer,
@ -487,6 +488,36 @@ Napi4Test('callback function return Promise and spawn', async (t) => {
test('object', (t) => {
t.deepEqual(listObjKeys({ name: 'John Doe', age: 20 }), ['name', 'age'])
t.deepEqual(createObj(), { test: 1 })
t.throws(
() =>
objectGetNamedPropertyShouldPerformTypecheck({
// @ts-expect-error
foo: '2',
bar: '3',
}),
{
message: `Object property 'foo' type mismatch. Expect value to be Number, but received String`,
code: 'InvalidArg',
},
)
t.throws(
() =>
objectGetNamedPropertyShouldPerformTypecheck({
foo: 2,
// @ts-expect-error
bar: 3,
}),
{
message: `Object property 'bar' type mismatch. Expect value to be String, but received Number`,
code: 'InvalidArg',
},
)
t.notThrows(() =>
objectGetNamedPropertyShouldPerformTypecheck({
foo: 2,
bar: '3',
}),
)
})
test('get str from object', (t) => {

View file

@ -476,6 +476,7 @@ module.exports.listObjKeys = nativeBinding.listObjKeys
module.exports.mapOption = nativeBinding.mapOption
module.exports.mutateExternal = nativeBinding.mutateExternal
module.exports.mutateTypedArray = nativeBinding.mutateTypedArray
module.exports.objectGetNamedPropertyShouldPerformTypecheck = nativeBinding.objectGetNamedPropertyShouldPerformTypecheck
module.exports.optionEnd = nativeBinding.optionEnd
module.exports.optionOnly = nativeBinding.optionOnly
module.exports.optionStart = nativeBinding.optionStart

View file

@ -505,6 +505,8 @@ export interface ObjectFieldClassInstance {
bird: Bird
}
export function objectGetNamedPropertyShouldPerformTypecheck(obj: { foo: number; bar: string; }): void
export interface ObjectOnlyFromJs {
count: number
callback: (err: Error | null, arg: number) => any

View file

@ -124,3 +124,10 @@ fn receive_object_only_from_js(
);
});
}
#[napi(ts_args_type = "obj: { foo: number; bar: string; }")]
fn object_get_named_property_should_perform_typecheck(obj: Object) -> Result<()> {
obj.get_named_property::<u32>("foo")?;
obj.get_named_property::<String>("bar")?;
Ok(())
}