This source file includes following definitions.
- ZEND_METHOD
- zend_valid_closure_binding
- ZEND_METHOD
- ZEND_METHOD
- zend_closure_get_constructor
- zend_closure_compare_objects
- zend_get_closure_invoke_method
- zend_get_closure_method_def
- zend_get_closure_this_ptr
- zend_closure_get_method
- zend_closure_read_property
- zend_closure_write_property
- zend_closure_get_property_ptr_ptr
- zend_closure_has_property
- zend_closure_unset_property
- zend_closure_free_storage
- zend_closure_new
- zend_closure_clone
- zend_closure_get_closure
- zend_closure_get_debug_info
- zend_closure_get_gc
- ZEND_METHOD
- zend_register_closure_ce
- zend_closure_internal_handler
- zend_create_closure
- zend_create_fake_closure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "zend.h"
24 #include "zend_API.h"
25 #include "zend_closures.h"
26 #include "zend_exceptions.h"
27 #include "zend_interfaces.h"
28 #include "zend_objects.h"
29 #include "zend_objects_API.h"
30 #include "zend_globals.h"
31
32 #define ZEND_CLOSURE_PRINT_NAME "Closure object"
33
34 #define ZEND_CLOSURE_PROPERTY_ERROR() \
35 zend_throw_error(NULL, "Closure object cannot have properties")
36
37
38 #define ZEND_ACC_FAKE_CLOSURE ZEND_ACC_INTERFACE
39
40 typedef struct _zend_closure {
41 zend_object std;
42 zend_function func;
43 zval this_ptr;
44 zend_class_entry *called_scope;
45 void (*orig_internal_handler)(INTERNAL_FUNCTION_PARAMETERS);
46 } zend_closure;
47
48
49 ZEND_API zend_class_entry *zend_ce_closure;
50 static zend_object_handlers closure_handlers;
51
52 ZEND_METHOD(Closure, __invoke)
53 {
54 zend_function *func = EX(func);
55 zval *arguments;
56
57 arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS());
58 if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
59 efree(arguments);
60 zend_throw_error(NULL, "Cannot get arguments for calling closure");
61 RETVAL_FALSE;
62 } else if (call_user_function_ex(CG(function_table), NULL, getThis(), return_value, ZEND_NUM_ARGS(), arguments, 1, NULL) == FAILURE) {
63 RETVAL_FALSE;
64 }
65 efree(arguments);
66
67
68 zend_string_release(func->internal_function.function_name);
69 efree(func);
70 #if ZEND_DEBUG
71 execute_data->func = NULL;
72 #endif
73 }
74
75
76 static zend_bool zend_valid_closure_binding(
77 zend_closure *closure, zval *newthis, zend_class_entry *scope)
78 {
79 zend_function *func = &closure->func;
80 if (newthis) {
81 if (func->common.fn_flags & ZEND_ACC_STATIC) {
82 zend_error(E_WARNING, "Cannot bind an instance to a static closure");
83 return 0;
84 }
85
86 if (func->type == ZEND_INTERNAL_FUNCTION && func->common.scope &&
87 !instanceof_function(Z_OBJCE_P(newthis), func->common.scope)) {
88
89 zend_error(E_WARNING, "Cannot bind internal method %s::%s() to object of class %s",
90 ZSTR_VAL(func->common.scope->name),
91 ZSTR_VAL(func->common.function_name),
92 ZSTR_VAL(Z_OBJCE_P(newthis)->name));
93 return 0;
94 }
95 } else if (!(func->common.fn_flags & ZEND_ACC_STATIC) && func->common.scope
96 && func->type == ZEND_INTERNAL_FUNCTION) {
97 zend_error(E_WARNING, "Cannot unbind $this of internal method");
98 return 0;
99 }
100
101 if (scope && scope != func->common.scope && scope->type == ZEND_INTERNAL_CLASS) {
102
103 zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s",
104 ZSTR_VAL(scope->name));
105 return 0;
106 }
107
108 if ((func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) && scope != func->common.scope) {
109 zend_error(E_WARNING, "Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()");
110 return 0;
111 }
112
113 return 1;
114 }
115
116
117
118
119 ZEND_METHOD(Closure, call)
120 {
121 zval *zclosure, *newthis, closure_result;
122 zend_closure *closure;
123 zend_fcall_info fci;
124 zend_fcall_info_cache fci_cache;
125 zval *my_params;
126 int my_param_count = 0;
127 zend_function my_function;
128 zend_object *newobj;
129
130 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o*", &newthis, &my_params, &my_param_count) == FAILURE) {
131 return;
132 }
133
134 zclosure = getThis();
135 closure = (zend_closure *) Z_OBJ_P(zclosure);
136
137 newobj = Z_OBJ_P(newthis);
138
139 if (!zend_valid_closure_binding(closure, newthis, Z_OBJCE_P(newthis))) {
140 return;
141 }
142
143
144 if (zend_fcall_info_init(zclosure, 0, &fci, &fci_cache, NULL, NULL) != SUCCESS) {
145 ZEND_ASSERT(0);
146 }
147
148 fci.retval = &closure_result;
149 fci.params = my_params;
150 fci.param_count = my_param_count;
151 fci.object = fci_cache.object = newobj;
152 fci_cache.initialized = 1;
153 fci_cache.called_scope = Z_OBJCE_P(newthis);
154
155 if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
156 zval new_closure;
157 zend_create_closure(&new_closure, fci_cache.function_handler, Z_OBJCE_P(newthis), closure->called_scope, newthis);
158 closure = (zend_closure *) Z_OBJ(new_closure);
159 fci_cache.function_handler = &closure->func;
160 } else {
161 memcpy(&my_function, fci_cache.function_handler, fci_cache.function_handler->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function));
162
163 my_function.common.scope = Z_OBJCE_P(newthis);
164 fci_cache.function_handler = &my_function;
165
166
167 if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
168 my_function.op_array.run_time_cache = emalloc(my_function.op_array.cache_size);
169 memset(my_function.op_array.run_time_cache, 0, my_function.op_array.cache_size);
170 }
171 }
172
173 if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) {
174 ZVAL_COPY_VALUE(return_value, &closure_result);
175 }
176
177 if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
178
179 --GC_REFCOUNT(&closure->std);
180 } else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
181 efree(my_function.op_array.run_time_cache);
182 }
183 }
184
185
186
187
188 ZEND_METHOD(Closure, bind)
189 {
190 zval *newthis, *zclosure, *scope_arg = NULL;
191 zend_closure *closure, *new_closure;
192 zend_class_entry *ce, *called_scope;
193
194 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) {
195 return;
196 }
197
198 closure = (zend_closure *)Z_OBJ_P(zclosure);
199
200 if (scope_arg != NULL) {
201 if (Z_TYPE_P(scope_arg) == IS_OBJECT) {
202 ce = Z_OBJCE_P(scope_arg);
203 } else if (Z_TYPE_P(scope_arg) == IS_NULL) {
204 ce = NULL;
205 } else {
206 zend_string *class_name = zval_get_string(scope_arg);
207 if (zend_string_equals_literal(class_name, "static")) {
208 ce = closure->func.common.scope;
209 } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) {
210 zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name));
211 zend_string_release(class_name);
212 RETURN_NULL();
213 }
214 zend_string_release(class_name);
215 }
216 } else {
217 ce = closure->func.common.scope;
218 }
219
220 if (!zend_valid_closure_binding(closure, newthis, ce)) {
221 return;
222 }
223
224 if (newthis) {
225 called_scope = Z_OBJCE_P(newthis);
226 } else {
227 called_scope = ce;
228 }
229
230 zend_create_closure(return_value, &closure->func, ce, called_scope, newthis);
231 new_closure = (zend_closure *) Z_OBJ_P(return_value);
232
233
234 if (ZEND_USER_CODE(closure->func.type) && (closure->func.common.scope != new_closure->func.common.scope || (closure->func.op_array.fn_flags & ZEND_ACC_NO_RT_ARENA))) {
235 new_closure->func.op_array.run_time_cache = emalloc(new_closure->func.op_array.cache_size);
236 memset(new_closure->func.op_array.run_time_cache, 0, new_closure->func.op_array.cache_size);
237
238 new_closure->func.op_array.fn_flags |= ZEND_ACC_NO_RT_ARENA;
239 }
240 }
241
242
243 static ZEND_COLD zend_function *zend_closure_get_constructor(zend_object *object)
244 {
245 zend_throw_error(NULL, "Instantiation of 'Closure' is not allowed");
246 return NULL;
247 }
248
249
250 static int zend_closure_compare_objects(zval *o1, zval *o2)
251 {
252 return (Z_OBJ_P(o1) != Z_OBJ_P(o2));
253 }
254
255
256 ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object)
257 {
258 zend_closure *closure = (zend_closure *)object;
259 zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function));
260 const uint32_t keep_flags =
261 ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_VARIADIC | ZEND_ACC_HAS_RETURN_TYPE;
262
263 invoke->common = closure->func.common;
264
265
266
267
268
269 invoke->type = ZEND_INTERNAL_FUNCTION;
270 invoke->internal_function.fn_flags =
271 ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & keep_flags);
272 if (closure->func.type != ZEND_INTERNAL_FUNCTION || (closure->func.common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
273 invoke->internal_function.fn_flags |=
274 ZEND_ACC_USER_ARG_INFO;
275 }
276 invoke->internal_function.handler = ZEND_MN(Closure___invoke);
277 invoke->internal_function.module = 0;
278 invoke->internal_function.scope = zend_ce_closure;
279 invoke->internal_function.function_name = zend_string_init(ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1, 0);
280 return invoke;
281 }
282
283
284 ZEND_API const zend_function *zend_get_closure_method_def(zval *obj)
285 {
286 zend_closure *closure = (zend_closure *)Z_OBJ_P(obj);
287 return &closure->func;
288 }
289
290
291 ZEND_API zval* zend_get_closure_this_ptr(zval *obj)
292 {
293 zend_closure *closure = (zend_closure *)Z_OBJ_P(obj);
294 return &closure->this_ptr;
295 }
296
297
298 static zend_function *zend_closure_get_method(zend_object **object, zend_string *method, const zval *key)
299 {
300 zend_string *lc_name;
301
302 lc_name = zend_string_tolower(method);
303 if (zend_string_equals_literal(method, ZEND_INVOKE_FUNC_NAME)) {
304 zend_string_release(lc_name);
305 return zend_get_closure_invoke_method(*object);
306 }
307 zend_string_release(lc_name);
308 return std_object_handlers.get_method(object, method, key);
309 }
310
311
312 static zval *zend_closure_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv)
313 {
314 ZEND_CLOSURE_PROPERTY_ERROR();
315 return &EG(uninitialized_zval);
316 }
317
318
319 static void zend_closure_write_property(zval *object, zval *member, zval *value, void **cache_slot)
320 {
321 ZEND_CLOSURE_PROPERTY_ERROR();
322 }
323
324
325 static zval *zend_closure_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot)
326 {
327 ZEND_CLOSURE_PROPERTY_ERROR();
328 return NULL;
329 }
330
331
332 static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot)
333 {
334 if (has_set_exists != 2) {
335 ZEND_CLOSURE_PROPERTY_ERROR();
336 }
337 return 0;
338 }
339
340
341 static void zend_closure_unset_property(zval *object, zval *member, void **cache_slot)
342 {
343 ZEND_CLOSURE_PROPERTY_ERROR();
344 }
345
346
347 static void zend_closure_free_storage(zend_object *object)
348 {
349 zend_closure *closure = (zend_closure *)object;
350
351 zend_object_std_dtor(&closure->std);
352
353 if (closure->func.type == ZEND_USER_FUNCTION) {
354 if (closure->func.op_array.fn_flags & ZEND_ACC_NO_RT_ARENA) {
355 efree(closure->func.op_array.run_time_cache);
356 closure->func.op_array.run_time_cache = NULL;
357 }
358 destroy_op_array(&closure->func.op_array);
359 }
360
361 if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
362 zval_ptr_dtor(&closure->this_ptr);
363 }
364 }
365
366
367 static zend_object *zend_closure_new(zend_class_entry *class_type)
368 {
369 zend_closure *closure;
370
371 closure = emalloc(sizeof(zend_closure));
372 memset(closure, 0, sizeof(zend_closure));
373
374 zend_object_std_init(&closure->std, class_type);
375 closure->std.handlers = &closure_handlers;
376
377 return (zend_object*)closure;
378 }
379
380
381 static zend_object *zend_closure_clone(zval *zobject)
382 {
383 zend_closure *closure = (zend_closure *)Z_OBJ_P(zobject);
384 zval result;
385
386 zend_create_closure(&result, &closure->func,
387 closure->func.common.scope, closure->called_scope, &closure->this_ptr);
388 return Z_OBJ(result);
389 }
390
391
392 int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr)
393 {
394 zend_closure *closure;
395
396 if (Z_TYPE_P(obj) != IS_OBJECT) {
397 return FAILURE;
398 }
399
400 closure = (zend_closure *)Z_OBJ_P(obj);
401 *fptr_ptr = &closure->func;
402 *ce_ptr = closure->called_scope;
403
404 if (obj_ptr) {
405 if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
406 *obj_ptr = Z_OBJ(closure->this_ptr);
407 } else {
408 *obj_ptr = NULL;
409 }
410 }
411 return SUCCESS;
412 }
413
414
415 static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp)
416 {
417 zend_closure *closure = (zend_closure *)Z_OBJ_P(object);
418 zval val;
419 struct _zend_arg_info *arg_info = closure->func.common.arg_info;
420 HashTable *debug_info;
421
422 *is_temp = 1;
423
424 ALLOC_HASHTABLE(debug_info);
425 zend_hash_init(debug_info, 8, NULL, ZVAL_PTR_DTOR, 0);
426
427 if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
428 HashTable *static_variables = closure->func.op_array.static_variables;
429 ZVAL_ARR(&val, zend_array_dup(static_variables));
430 zend_hash_str_update(debug_info, "static", sizeof("static")-1, &val);
431 }
432
433 if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
434 Z_ADDREF(closure->this_ptr);
435 zend_hash_str_update(debug_info, "this", sizeof("this")-1, &closure->this_ptr);
436 }
437
438 if (arg_info &&
439 (closure->func.common.num_args ||
440 (closure->func.common.fn_flags & ZEND_ACC_VARIADIC))) {
441 uint32_t i, num_args, required = closure->func.common.required_num_args;
442
443 array_init(&val);
444
445 num_args = closure->func.common.num_args;
446 if (closure->func.common.fn_flags & ZEND_ACC_VARIADIC) {
447 num_args++;
448 }
449 for (i = 0; i < num_args; i++) {
450 zend_string *name;
451 zval info;
452 if (arg_info->name) {
453 name = zend_strpprintf(0, "%s$%s",
454 arg_info->pass_by_reference ? "&" : "",
455 ZSTR_VAL(arg_info->name));
456 } else {
457 name = zend_strpprintf(0, "%s$param%d",
458 arg_info->pass_by_reference ? "&" : "",
459 i + 1);
460 }
461 ZVAL_NEW_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>"));
462 zend_hash_update(Z_ARRVAL(val), name, &info);
463 zend_string_release(name);
464 arg_info++;
465 }
466 zend_hash_str_update(debug_info, "parameter", sizeof("parameter")-1, &val);
467 }
468
469 return debug_info;
470 }
471
472
473 static HashTable *zend_closure_get_gc(zval *obj, zval **table, int *n)
474 {
475 zend_closure *closure = (zend_closure *)Z_OBJ_P(obj);
476
477 *table = Z_TYPE(closure->this_ptr) != IS_NULL ? &closure->this_ptr : NULL;
478 *n = Z_TYPE(closure->this_ptr) != IS_NULL ? 1 : 0;
479 return (closure->func.type == ZEND_USER_FUNCTION) ?
480 closure->func.op_array.static_variables : NULL;
481 }
482
483
484
485
486 ZEND_COLD ZEND_METHOD(Closure, __construct)
487 {
488 zend_throw_error(NULL, "Instantiation of 'Closure' is not allowed");
489 }
490
491
492 ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bindto, 0, 0, 1)
493 ZEND_ARG_INFO(0, newthis)
494 ZEND_ARG_INFO(0, newscope)
495 ZEND_END_ARG_INFO()
496
497 ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bind, 0, 0, 2)
498 ZEND_ARG_INFO(0, closure)
499 ZEND_ARG_INFO(0, newthis)
500 ZEND_ARG_INFO(0, newscope)
501 ZEND_END_ARG_INFO()
502
503 ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_call, 0, 0, 1)
504 ZEND_ARG_INFO(0, newthis)
505 ZEND_ARG_VARIADIC_INFO(0, parameters)
506 ZEND_END_ARG_INFO()
507
508 static const zend_function_entry closure_functions[] = {
509 ZEND_ME(Closure, __construct, NULL, ZEND_ACC_PRIVATE)
510 ZEND_ME(Closure, bind, arginfo_closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
511 ZEND_MALIAS(Closure, bindTo, bind, arginfo_closure_bindto, ZEND_ACC_PUBLIC)
512 ZEND_ME(Closure, call, arginfo_closure_call, ZEND_ACC_PUBLIC)
513 ZEND_FE_END
514 };
515
516 void zend_register_closure_ce(void)
517 {
518 zend_class_entry ce;
519
520 INIT_CLASS_ENTRY(ce, "Closure", closure_functions);
521 zend_ce_closure = zend_register_internal_class(&ce);
522 zend_ce_closure->ce_flags |= ZEND_ACC_FINAL;
523 zend_ce_closure->create_object = zend_closure_new;
524 zend_ce_closure->serialize = zend_class_serialize_deny;
525 zend_ce_closure->unserialize = zend_class_unserialize_deny;
526
527 memcpy(&closure_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
528 closure_handlers.free_obj = zend_closure_free_storage;
529 closure_handlers.clone_obj = NULL;
530 closure_handlers.get_constructor = zend_closure_get_constructor;
531 closure_handlers.get_method = zend_closure_get_method;
532 closure_handlers.write_property = zend_closure_write_property;
533 closure_handlers.read_property = zend_closure_read_property;
534 closure_handlers.get_property_ptr_ptr = zend_closure_get_property_ptr_ptr;
535 closure_handlers.has_property = zend_closure_has_property;
536 closure_handlers.unset_property = zend_closure_unset_property;
537 closure_handlers.compare_objects = zend_closure_compare_objects;
538 closure_handlers.clone_obj = zend_closure_clone;
539 closure_handlers.get_debug_info = zend_closure_get_debug_info;
540 closure_handlers.get_closure = zend_closure_get_closure;
541 closure_handlers.get_gc = zend_closure_get_gc;
542 }
543
544
545 static void zend_closure_internal_handler(INTERNAL_FUNCTION_PARAMETERS)
546 {
547 zend_closure *closure = (zend_closure*)EX(func)->common.prototype;
548 closure->orig_internal_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
549 OBJ_RELEASE((zend_object*)closure);
550 EX(func) = NULL;
551 }
552
553
554 ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr)
555 {
556 zend_closure *closure;
557
558 object_init_ex(res, zend_ce_closure);
559
560 closure = (zend_closure *)Z_OBJ_P(res);
561
562 if ((scope == NULL) && this_ptr && (Z_TYPE_P(this_ptr) != IS_UNDEF)) {
563
564
565 scope = zend_ce_closure;
566 }
567
568 if (func->type == ZEND_USER_FUNCTION) {
569 memcpy(&closure->func, func, sizeof(zend_op_array));
570 closure->func.common.prototype = (zend_function*)closure;
571 closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
572 if (closure->func.op_array.static_variables) {
573 HashTable *static_variables = closure->func.op_array.static_variables;
574
575 ALLOC_HASHTABLE(closure->func.op_array.static_variables);
576 zend_hash_init(closure->func.op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
577 zend_hash_apply_with_arguments(static_variables, zval_copy_static_var, 1, closure->func.op_array.static_variables);
578 }
579 if (UNEXPECTED(!closure->func.op_array.run_time_cache)) {
580 closure->func.op_array.run_time_cache = func->op_array.run_time_cache = zend_arena_alloc(&CG(arena), func->op_array.cache_size);
581 memset(func->op_array.run_time_cache, 0, func->op_array.cache_size);
582 }
583 if (closure->func.op_array.refcount) {
584 (*closure->func.op_array.refcount)++;
585 }
586 } else {
587 memcpy(&closure->func, func, sizeof(zend_internal_function));
588 closure->func.common.prototype = (zend_function*)closure;
589 closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
590
591 if (UNEXPECTED(closure->func.internal_function.handler == zend_closure_internal_handler)) {
592
593 zend_closure *nested = (zend_closure*)((char*)func - XtOffsetOf(zend_closure, func));
594 ZEND_ASSERT(nested->std.ce == zend_ce_closure);
595 closure->orig_internal_handler = nested->orig_internal_handler;
596 } else {
597 closure->orig_internal_handler = closure->func.internal_function.handler;
598 }
599 closure->func.internal_function.handler = zend_closure_internal_handler;
600 if (!func->common.scope) {
601
602 this_ptr = NULL;
603 scope = NULL;
604 }
605 }
606
607 ZVAL_UNDEF(&closure->this_ptr);
608
609
610 closure->func.common.scope = scope;
611 closure->called_scope = called_scope;
612 if (scope) {
613 closure->func.common.fn_flags |= ZEND_ACC_PUBLIC;
614 if (this_ptr && Z_TYPE_P(this_ptr) == IS_OBJECT && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) {
615 ZVAL_COPY(&closure->this_ptr, this_ptr);
616 }
617 }
618 }
619
620
621 ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr)
622 {
623 zend_closure *closure;
624
625 zend_create_closure(res, func, scope, called_scope, this_ptr);
626
627 closure = (zend_closure *)Z_OBJ_P(res);
628 closure->func.common.fn_flags |= ZEND_ACC_FAKE_CLOSURE;
629 }
630
631
632
633
634
635
636
637
638