Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2e01785

Browse files
authored
fix invocation of functions with type hint (#220)
1 parent84adb0b commit2e01785

File tree

5 files changed

+91
-51
lines changed

5 files changed

+91
-51
lines changed

‎phper-test/src/cli.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ pub fn test_php_scripts_with_condition(
179179
"execute php test command");
180180

181181
if !condition(output){
182+
eprintln!("--- stdout ---\n{}", stdout);
183+
eprintln!("--- stderr ---\n{}", stderr);
182184
panic!("test php file `{}` failed", path);
183185
}
184186
}

‎phper/src/functions.rs‎

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,11 @@ use std::{
2828
collections::HashMap,
2929
ffi::{CStr,CString},
3030
marker::PhantomData,
31-
mem::{ManuallyDrop,size_of,transmute, zeroed},
31+
mem::{ManuallyDrop, transmute, zeroed},
3232
ptr::{self, null_mut},
3333
rc::Rc,
34-
slice,
3534
};
3635

37-
/// Used to mark the arguments obtained by the invoke function as mysterious
38-
/// codes from phper
39-
constINVOKE_MYSTERIOUS_CODE:&[u8] =b"PHPER";
40-
4136
/// Used to find the handler in the invoke function.
4237
pub(crate)typeHandlerMap =HashMap<(Option<CString>,CString),Rc<dynCallable>>;
4338

@@ -371,9 +366,6 @@ impl FunctionEntry {
371366

372367
infos.push(zeroed::<zend_internal_arg_info>());
373368

374-
// Will be checked in `invoke` function.
375-
infos.push(Self::create_mysterious_code());
376-
377369
let raw_handler = handler.as_ref().map(|_| invokeas_);
378370

379371
ifletSome(handler) = handler{
@@ -397,22 +389,12 @@ impl FunctionEntry {
397389
}
398390
}
399391
}
400-
401-
unsafefncreate_mysterious_code() ->zend_internal_arg_info{
402-
unsafe{
403-
letmut mysterious_code =[0u8;size_of::<zend_internal_arg_info>()];
404-
for(i, n)inINVOKE_MYSTERIOUS_CODE.iter().enumerate(){
405-
mysterious_code[i] =*n;
406-
}
407-
transmute(mysterious_code)
408-
}
409-
}
410392
}
411393

412394
/// Builder for registering php function.
413395
pubstructFunctionEntity{
414-
name:CString,
415-
handler:Rc<dynCallable>,
396+
pub(crate)name:CString,
397+
pub(crate)handler:Rc<dynCallable>,
416398
arguments:Vec<Argument>,
417399
return_type:Option<ReturnType>,
418400
}
@@ -797,7 +779,6 @@ impl ZFunc {
797779
pub(crate)unionCallableTranslator{
798780
pub(crate)callable:*constdynCallable,
799781
pub(crate)internal_arg_info:zend_internal_arg_info,
800-
pub(crate)arg_info:zend_arg_info,
801782
}
802783

803784
/// The entry for all registered PHP functions.
@@ -806,25 +787,7 @@ unsafe extern "C" fn invoke(execute_data: *mut zend_execute_data, return_value:
806787
let execute_data =ExecuteData::from_mut_ptr(execute_data);
807788
let return_value =ZVal::from_mut_ptr(return_value);
808789

809-
let num_args = execute_data.common_num_args();
810-
let arg_info = execute_data.common_arg_info();
811-
812-
// should be mysterious code
813-
let mysterious_arg_info = arg_info.offset((num_args +1)asisize);
814-
let mysterious_code = slice::from_raw_parts(
815-
mysterious_arg_infoas*constu8,
816-
INVOKE_MYSTERIOUS_CODE.len(),
817-
);
818-
819-
let handler =if mysterious_code ==INVOKE_MYSTERIOUS_CODE{
820-
// hiddden real handler
821-
let last_arg_info = arg_info.offset((num_args +2)asisize);
822-
let translator =CallableTranslator{
823-
arg_info:*last_arg_info,
824-
};
825-
let handler = translator.callable;
826-
handler.as_ref().expect("handler is null")
827-
}else{
790+
let handler ={
828791
let function_name = execute_data
829792
.func()
830793
.get_function_name()

‎phper/src/modules.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ unsafe extern "C" fn module_startup(_type: c_int, module_number: c_int) -> c_int
5555
interface_entity.init();
5656
}
5757

58+
for function_entityin&module.function_entities{
59+
module.handler_map.insert(
60+
(None, function_entity.name.clone()),
61+
function_entity.handler.clone(),
62+
);
63+
}
64+
5865
for class_entityin&module.class_entities{
5966
let ce = class_entity.init();
6067
class_entity.declare_properties(ce);

‎tests/integration/src/typehints.rs‎

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
// See the Mulan PSL v2 for more details.
1010

1111
use phper::{
12+
arrays::ZArray,
1213
classes::{ClassEntity,Interface,InterfaceEntity,StateClass,Visibility},
1314
functions::{Argument,ReturnType},
1415
modules::Module,
1516
types::{ArgumentTypeHint,ReturnTypeHint},
1617
values::ZVal,
1718
};
19+
use std::convert::Infallible;
1820

1921
constI_FOO:&str =r"IntegrationTest\TypeHints\IFoo";
2022

@@ -26,6 +28,45 @@ pub fn integrate(module: &mut Module) {
2628
module.add_class(make_arg_typehint_class());
2729
module.add_class(make_return_typehint_class());
2830
module.add_class(make_arg_default_value_class());
31+
module
32+
.add_function(
33+
"integration_function_return_bool",
34+
|_| ->Result<bool,Infallible>{Ok(true)},
35+
)
36+
.return_type(ReturnType::new(ReturnTypeHint::Bool));
37+
module
38+
.add_function(
39+
"integration_function_return_int",
40+
|_| ->Result<i64,Infallible>{Ok(42)},
41+
)
42+
.return_type(ReturnType::new(ReturnTypeHint::Int));
43+
module
44+
.add_function(
45+
"integration_function_return_float",
46+
|_| ->Result<f64,Infallible>{Ok(1.234)},
47+
)
48+
.return_type(ReturnType::new(ReturnTypeHint::Float));
49+
module
50+
.add_function(
51+
"integration_function_return_string",
52+
|_| ->Result<&'staticstr,Infallible>{Ok("phper")},
53+
)
54+
.return_type(ReturnType::new(ReturnTypeHint::String));
55+
module
56+
.add_function(
57+
"integration_function_return_array",
58+
|_| ->Result<ZArray,Infallible>{Ok(ZArray::new())},
59+
)
60+
.return_type(ReturnType::new(ReturnTypeHint::Array));
61+
module
62+
.add_function(
63+
"integration_function_return_mixed",
64+
|_| ->Result<ZVal,Infallible>{Ok(ZVal::from(1.23))},
65+
)
66+
.return_type(ReturnType::new(ReturnTypeHint::Mixed));
67+
module
68+
.add_function("integration_function_return_void", |_| phper::ok(()))
69+
.return_type(ReturnType::new(ReturnTypeHint::Void));
2970
module
3071
.add_function("integration_function_typehints", |_| phper::ok(()))
3172
.argument(
@@ -455,11 +496,9 @@ fn make_return_typehint_class() -> ClassEntity<()> {
455496
.return_type(ReturnType::new(ReturnTypeHint::Null));
456497

457498
class
458-
.add_method(
459-
"returnString",
460-
Visibility::Public,
461-
move |_, _| phper::ok(()),
462-
)
499+
.add_method("returnString",Visibility::Public,move |_, _|{
500+
phper::ok("phper")
501+
})
463502
.return_type(ReturnType::new(ReturnTypeHint::String));
464503

465504
class
@@ -469,7 +508,9 @@ fn make_return_typehint_class() -> ClassEntity<()> {
469508
.return_type(ReturnType::new(ReturnTypeHint::String).allow_null());
470509

471510
class
472-
.add_method("returnBool",Visibility::Public,move |_, _| phper::ok(()))
511+
.add_method("returnBool",Visibility::Public,move |_, _|{
512+
phper::ok(true)
513+
})
473514
.return_type(ReturnType::new(ReturnTypeHint::Bool));
474515

475516
class
@@ -479,7 +520,7 @@ fn make_return_typehint_class() -> ClassEntity<()> {
479520
.return_type(ReturnType::new(ReturnTypeHint::Bool).allow_null());
480521

481522
class
482-
.add_method("returnInt",Visibility::Public,move |_, _| phper::ok(()))
523+
.add_method("returnInt",Visibility::Public,move |_, _| phper::ok(42))
483524
.return_type(ReturnType::new(ReturnTypeHint::Int));
484525

485526
class
@@ -489,7 +530,9 @@ fn make_return_typehint_class() -> ClassEntity<()> {
489530
.return_type(ReturnType::new(ReturnTypeHint::Int).allow_null());
490531

491532
class
492-
.add_method("returnFloat",Visibility::Public,move |_, _| phper::ok(()))
533+
.add_method("returnFloat",Visibility::Public,move |_, _|{
534+
phper::ok(1.234)
535+
})
493536
.return_type(ReturnType::new(ReturnTypeHint::Float));
494537

495538
class
@@ -499,7 +542,9 @@ fn make_return_typehint_class() -> ClassEntity<()> {
499542
.return_type(ReturnType::new(ReturnTypeHint::Float).allow_null());
500543

501544
class
502-
.add_method("returnArray",Visibility::Public,move |_, _| phper::ok(()))
545+
.add_method("returnArray",Visibility::Public,move |_, _|{
546+
phper::ok(ZArray::new())
547+
})
503548
.return_type(ReturnType::new(ReturnTypeHint::Array));
504549

505550
class

‎tests/integration/tests/php/typehints.php‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,27 @@ public function setValue($value): void {
209209
echo"PASS" .PHP_EOL;
210210
}
211211
assert_eq('void',$reflection->getReturnType()->getName(),'integration_function_typehints return type is void');
212-
}
212+
}
213+
214+
//invoke type-hinted functions to exercise handlers
215+
echoPHP_EOL .'Testing return type-hinted function invocation' .PHP_EOL;
216+
assert_true(integration_function_return_bool());
217+
assert_eq(42,integration_function_return_int());
218+
assert_eq(1.234,integration_function_return_float());
219+
assert_eq('phper',integration_function_return_string());
220+
assert_eq(array(),integration_function_return_array());
221+
assert_eq(1.23,integration_function_return_mixed());
222+
223+
//invoke type-hinted class methods to exercise handlers
224+
echoPHP_EOL .'Testing return type-hinted method invocation' .PHP_EOL;
225+
$cls =new \IntegrationTest\TypeHints\ReturnTypeHintTest();
226+
assert_eq(true,$cls->returnBool(),'returnBool');
227+
assert_eq(null,$cls->returnBoolNullable(),'returnBoolNullable');
228+
assert_eq(42,$cls->returnInt(),'returnInt');
229+
assert_eq(null,$cls->returnIntNullable(),'returnIntNullable');
230+
assert_eq(1.234,$cls->returnFloat(),'returnFloat');
231+
assert_eq(null,$cls->returnFloatNullable(),'returnFloatNullable');
232+
assert_eq('phper',$cls->returnString(),'returnString');
233+
assert_eq(null,$cls->returnStringNullable(),'returnStringNullable');
234+
assert_eq(array(),$cls->returnArray(),'returnArray');
235+
assert_eq(null,$cls->returnArrayNullable(),'returnArrayNullable');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp