magic_func.phpt 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. --TEST--
  2. Test V8::executeString() : Object with magic functions
  3. --SKIPIF--
  4. <?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
  5. --FILE--
  6. <?php
  7. class Foo {
  8. var $bar = 'foobar';
  9. var $nullprop = null;
  10. function __construct() {
  11. echo "called constructor: ";
  12. var_dump(func_get_args());
  13. }
  14. function MyOwnFunc() {
  15. echo "called MyOwnFunc\n";
  16. }
  17. function __Get($name) {
  18. echo "Called __get(): ";
  19. var_dump($name);
  20. return null;
  21. }
  22. function __Set($name, $args) {
  23. echo "Called __set(): ";
  24. var_dump($name, $args);
  25. }
  26. function __Isset($name) {
  27. echo "Called __isset(): ";
  28. var_dump($name);
  29. return true;
  30. }
  31. function __unSet($name) {
  32. echo "Called __unset(): ";
  33. var_dump($name);
  34. }
  35. function __call($name, $args) {
  36. echo "Called __call(): ";
  37. var_dump($name, $args);
  38. return "call";
  39. }
  40. function __Invoke($name, $arg1, $arg2) {
  41. echo "Called __invoke(): ";
  42. var_dump(func_get_args());
  43. return 'foobar';
  44. }
  45. function __toString() {
  46. echo "Called __tostring: ";
  47. return $this->bar;
  48. }
  49. }
  50. class Bar {
  51. function foo($arg1, $arg2, $arg3) {
  52. echo "Called foo(): ";
  53. var_dump(func_get_args());
  54. return "test";
  55. }
  56. }
  57. $blaa = new V8Js();
  58. $blaa->obj = $obj = new Foo;
  59. try {
  60. echo "__invoke() [PHP]\n";
  61. var_dump($obj('arg1','arg2','arg3'));
  62. echo "__invoke() [JS]\n";
  63. $blaa->executeString("var_dump(PHP.obj('arg1','arg2','arg3'));", "invoke_test1 #1.js");
  64. echo "------------\n";
  65. echo " __invoke() with new [PHP]\n";
  66. $myobj = new $obj('arg1','arg2','arg3'); $myobj->myownfunc();
  67. echo " __invoke() with new [JS]\n";
  68. $blaa->executeString("myobj = new PHP.obj('arg1','arg2','arg3'); myobj.myownfunc();", "invoke_test2 #2.js");
  69. echo "------------\n";
  70. echo " __tostring() [PHP]\n";
  71. echo $obj; echo "\n";
  72. echo " __tostring() [JS]\n";
  73. $blaa->executeString('print(PHP.obj + "\n");', "tostring_test #3.js");
  74. echo "------------\n";
  75. echo " __isset() not called with existing property [PHP]\n";
  76. if (isset($obj->bar)) { echo "bar exists\n"; }
  77. echo " __isset() not called with existing property [JS]\n";
  78. $blaa->executeString('if ("bar" in PHP.obj) print("bar exists\n");', "isset_test1 #4.js");
  79. echo "------------\n";
  80. echo " __isset() with non-existing property [PHP]\n";
  81. if (!isset($obj->foobar)) { echo "foobar does not exist\n"; } else { echo "We called __isset and it said yes!\n"; }
  82. echo " __isset() with non-existing property [JS]\n";
  83. $blaa->executeString('if (!("foobar" in PHP.obj)) print("foobar does not exist\n"); else print("We called __isset and it said yes!\n");', "isset_test2 #5.js");
  84. echo "------------\n";
  85. echo " in works like isset [PHP]\n";
  86. echo "nullprop is ", (isset($obj->nullprop) ? "" : "not "), "set\n";
  87. echo " in works like isset [JS]\n";
  88. $blaa->executeString('print("nullprop is ", ("nullprop" in PHP.obj) ? "" : "not ", "set\n");', "isset_test3 #6.js");
  89. echo "------------\n";
  90. echo " __get() not called with existing property [PHP]\n";
  91. var_dump($obj->bar);
  92. echo " __get() not called with existing property [JS]\n";
  93. $blaa->executeString('var_dump(PHP.obj.bar);', "get_test1 #7.js");
  94. echo "------------\n";
  95. echo " __get() with non-existing property [PHP]\n";
  96. var_dump($obj->fooish);
  97. echo " __get() with non-existing property [JS]\n";
  98. $blaa->executeString('var_dump(PHP.obj.fooish);', "get_test2 #8.js");
  99. echo "------------\n";
  100. echo " __unset() with non-existing property [PHP]\n";
  101. unset($obj->foobar);
  102. echo " __unset() with non-existing property [JS]\n";
  103. $blaa->executeString('delete PHP.obj.foobar;', "unset_test1 #9.js");
  104. echo "------------\n";
  105. echo " __unset() with existing property [PHP]\n";
  106. $obj2 = new Foo; unset($obj2->bar);
  107. echo " __unset() with existing property [JS]\n";
  108. $blaa->obj2 = new Foo;
  109. $blaa->executeString('delete PHP.obj2.bar;', "unset_test2 #10.js");
  110. echo " fetching the unset property [PHP]\n";
  111. var_dump($obj2->bar);
  112. echo " fetching the unset property [JS]\n";
  113. $blaa->executeString('var_dump(PHP.obj2.bar);', "unset_test3 #11.js");
  114. echo "------------\n";
  115. echo " __call() [PHP]\n";
  116. var_dump($obj->fooish(1,2,3));
  117. echo " __call() [JS]\n";
  118. # note that 'PHP.obj.fooish(1,2,3)' won't work in JS, we need to use the
  119. # '__call' pseudo-method.
  120. $blaa->executeString('var_dump(PHP.obj.__call("fooish", [1,2,3]));', "call_test1 #12.js");
  121. echo "------------\n";
  122. # the __call pseudo-method should work in JS even if the PHP class doesn't
  123. # define an explicit __call magic function. This makes it always safe to
  124. # use __call() if you want to be sure that any __call() handlers are invoked
  125. # (bypassing __get handlers, as is it done in PHP)
  126. $blaa->obj3 = $obj3 = new Bar;
  127. echo " __call() w/o handler [PHP]\n";
  128. var_dump($obj3->foo(1,2,3));
  129. echo " __call() w/o handler [JS]\n";
  130. $blaa->executeString('var_dump(PHP.obj3.__call("foo", [1,2,3]));', "call_test2 #13.js");
  131. echo "------------\n";
  132. # The Bar object should inherit toString() and hasOwnProperty() methods
  133. # from Object
  134. echo " __toString in Bar [PHP]\n";
  135. var_dump(method_exists( $obj3, '__toString' ));
  136. echo " toString in Bar [PHP]\n";
  137. var_dump(method_exists( $obj3, 'toString' ));
  138. echo " hasOwnProperty in Bar [PHP]\n";
  139. var_dump(method_exists( $obj3, 'hasOwnProperty' ));
  140. echo " __toString in Bar [JS]\n";
  141. $blaa->executeString('var_dump("__toString" in PHP.obj3 && typeof PHP.obj3.__toString == "function");', "inherit_test1 #14.js");
  142. # use '$toString' if you actually wanted to check for a PHP property
  143. # named 'toString' in Bar (instead of the inherited JavaScript property)
  144. echo " toString in Bar [JS]\n";
  145. $blaa->executeString('var_dump("toString" in PHP.obj3 && typeof PHP.obj3.toString == "function");', "inherit_test1 #15.js");
  146. # use '$hasOwnProperty' if you actually wanted to check for a PHP property
  147. # named 'hasOwnProperty' in Bar (instead of the inherited JavaScript property)
  148. echo " hasOwnProperty in Bar [JS]\n";
  149. $blaa->executeString('var_dump("hasOwnProperty" in PHP.obj3 && typeof PHP.obj3.hasOwnProperty == "function");', "inherit_test1 #16.js");
  150. echo "------------\n";
  151. } catch (V8JsScriptException $e) {
  152. echo $e->getMessage(), "\n";
  153. }
  154. ?>
  155. ===EOF===
  156. --EXPECT--
  157. called constructor: array(0) {
  158. }
  159. __invoke() [PHP]
  160. Called __invoke(): array(3) {
  161. [0]=>
  162. string(4) "arg1"
  163. [1]=>
  164. string(4) "arg2"
  165. [2]=>
  166. string(4) "arg3"
  167. }
  168. string(6) "foobar"
  169. __invoke() [JS]
  170. Called __invoke(): array(3) {
  171. [0]=>
  172. string(4) "arg1"
  173. [1]=>
  174. string(4) "arg2"
  175. [2]=>
  176. string(4) "arg3"
  177. }
  178. string(6) "foobar"
  179. ------------
  180. __invoke() with new [PHP]
  181. called constructor: array(3) {
  182. [0]=>
  183. string(4) "arg1"
  184. [1]=>
  185. string(4) "arg2"
  186. [2]=>
  187. string(4) "arg3"
  188. }
  189. called MyOwnFunc
  190. __invoke() with new [JS]
  191. called constructor: array(3) {
  192. [0]=>
  193. string(4) "arg1"
  194. [1]=>
  195. string(4) "arg2"
  196. [2]=>
  197. string(4) "arg3"
  198. }
  199. called MyOwnFunc
  200. ------------
  201. __tostring() [PHP]
  202. Called __tostring: foobar
  203. __tostring() [JS]
  204. Called __get(): string(7) "valueOf"
  205. Called __tostring: foobar
  206. ------------
  207. __isset() not called with existing property [PHP]
  208. bar exists
  209. __isset() not called with existing property [JS]
  210. bar exists
  211. ------------
  212. __isset() with non-existing property [PHP]
  213. Called __isset(): string(6) "foobar"
  214. We called __isset and it said yes!
  215. __isset() with non-existing property [JS]
  216. Called __isset(): string(6) "foobar"
  217. We called __isset and it said yes!
  218. ------------
  219. in works like isset [PHP]
  220. nullprop is not set
  221. in works like isset [JS]
  222. nullprop is not set
  223. ------------
  224. __get() not called with existing property [PHP]
  225. string(6) "foobar"
  226. __get() not called with existing property [JS]
  227. string(6) "foobar"
  228. ------------
  229. __get() with non-existing property [PHP]
  230. Called __get(): string(6) "fooish"
  231. NULL
  232. __get() with non-existing property [JS]
  233. Called __get(): string(6) "fooish"
  234. NULL
  235. ------------
  236. __unset() with non-existing property [PHP]
  237. Called __unset(): string(6) "foobar"
  238. __unset() with non-existing property [JS]
  239. Called __unset(): string(6) "foobar"
  240. ------------
  241. __unset() with existing property [PHP]
  242. called constructor: array(0) {
  243. }
  244. __unset() with existing property [JS]
  245. called constructor: array(0) {
  246. }
  247. fetching the unset property [PHP]
  248. Called __get(): string(3) "bar"
  249. NULL
  250. fetching the unset property [JS]
  251. Called __get(): string(3) "bar"
  252. NULL
  253. ------------
  254. __call() [PHP]
  255. Called __call(): string(6) "fooish"
  256. array(3) {
  257. [0]=>
  258. int(1)
  259. [1]=>
  260. int(2)
  261. [2]=>
  262. int(3)
  263. }
  264. string(4) "call"
  265. __call() [JS]
  266. Called __call(): string(6) "fooish"
  267. array(3) {
  268. [0]=>
  269. int(1)
  270. [1]=>
  271. int(2)
  272. [2]=>
  273. int(3)
  274. }
  275. string(4) "call"
  276. ------------
  277. __call() w/o handler [PHP]
  278. Called foo(): array(3) {
  279. [0]=>
  280. int(1)
  281. [1]=>
  282. int(2)
  283. [2]=>
  284. int(3)
  285. }
  286. string(4) "test"
  287. __call() w/o handler [JS]
  288. Called foo(): array(3) {
  289. [0]=>
  290. int(1)
  291. [1]=>
  292. int(2)
  293. [2]=>
  294. int(3)
  295. }
  296. string(4) "test"
  297. ------------
  298. __toString in Bar [PHP]
  299. bool(false)
  300. toString in Bar [PHP]
  301. bool(false)
  302. hasOwnProperty in Bar [PHP]
  303. bool(false)
  304. __toString in Bar [JS]
  305. bool(false)
  306. toString in Bar [JS]
  307. bool(true)
  308. hasOwnProperty in Bar [JS]
  309. bool(true)
  310. ------------
  311. ===EOF===