Updated from some -dev modules to alpha, beta or full releases
[yaffs-website] / vendor / psy / psysh / src / ExecutionClosure.php
1 <?php
2
3 /*
4  * This file is part of Psy Shell.
5  *
6  * (c) 2012-2018 Justin Hileman
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Psy;
13
14 /**
15  * The Psy Shell's execution scope.
16  */
17 class ExecutionClosure
18 {
19     const NOOP_INPUT = 'return null;';
20
21     private $closure;
22
23     /**
24      * @param Shell $__psysh__
25      */
26     public function __construct(Shell $__psysh__)
27     {
28         $this->setClosure($__psysh__, function () use ($__psysh__) {
29             try {
30                 // Restore execution scope variables
31                 extract($__psysh__->getScopeVariables(false));
32
33                 // Buffer stdout; we'll need it later
34                 ob_start([$__psysh__, 'writeStdout'], 1);
35
36                 // Convert all errors to exceptions
37                 set_error_handler([$__psysh__, 'handleError']);
38
39                 // Evaluate the current code buffer
40                 $_ = eval($__psysh__->onExecute($__psysh__->flushCode() ?: ExecutionClosure::NOOP_INPUT));
41             } catch (\Throwable $_e) {
42                 // Clean up on our way out.
43                 restore_error_handler();
44                 if (ob_get_level() > 0) {
45                     ob_end_clean();
46                 }
47
48                 throw $_e;
49             } catch (\Exception $_e) {
50                 // Clean up on our way out.
51                 restore_error_handler();
52                 if (ob_get_level() > 0) {
53                     ob_end_clean();
54                 }
55
56                 throw $_e;
57             }
58
59             // Won't be needing this anymore
60             restore_error_handler();
61
62             // Flush stdout (write to shell output, plus save to magic variable)
63             ob_end_flush();
64
65             // Save execution scope variables for next time
66             $__psysh__->setScopeVariables(get_defined_vars());
67
68             return $_;
69         });
70     }
71
72     /**
73      * Set the closure instance.
74      *
75      * @param Shell    $psysh
76      * @param \Closure $closure
77      */
78     protected function setClosure(Shell $shell, \Closure $closure)
79     {
80         if (self::shouldBindClosure()) {
81             $that = $shell->getBoundObject();
82             if (is_object($that)) {
83                 $closure = $closure->bindTo($that, get_class($that));
84             } else {
85                 $closure = $closure->bindTo(null, $shell->getBoundClass());
86             }
87         }
88
89         $this->closure = $closure;
90     }
91
92     /**
93      * Go go gadget closure.
94      *
95      * @return mixed
96      */
97     public function execute()
98     {
99         $closure = $this->closure;
100
101         return $closure();
102     }
103
104     /**
105      * Decide whether to bind the execution closure.
106      *
107      * @return bool
108      */
109     protected static function shouldBindClosure()
110     {
111         // skip binding on HHVM < 3.5.0
112         // see https://github.com/facebook/hhvm/issues/1203
113         if (defined('HHVM_VERSION')) {
114             return version_compare(HHVM_VERSION, '3.5.0', '>=');
115         }
116
117         return true;
118     }
119 }