22
33#include < nan.h>
44extern " C" {
5- #include " php.h"
6- #include " Zend/zend.h"
7- #include " Zend/zend_exceptions.h"
8- #include " Zend/zend_types.h"
5+ #include < main/ php.h>
6+ #include < Zend/zend.h>
7+ #include < Zend/zend_exceptions.h>
8+ #include < Zend/zend_types.h>
99}
1010
1111#include " node_php_jsobject_class.h"
12+
13+ #include " macros.h"
1214#include " messages.h"
1315#include " values.h"
14- #include " macros.h"
1516
1617#define USE_MAGIC_ISSET 0
1718
@@ -248,6 +249,76 @@ PHP_METHOD(JsObject, __unset) {
248249 msg.retval_ .ToPhp (obj->channel , return_value, return_value_ptr TSRMLS_CC);
249250}
250251
252+ class JsInvokeMethodMsg : public MessageToJs {
253+ Value object_;
254+ Value member_;
255+ ulong argc_;
256+ Value *argv_;
257+ public:
258+ JsInvokeMethodMsg (ObjectMapper *m, objid_t objId, zval *member, ulong argc, zval **argv)
259+ : MessageToJs(m), object_(), member_(m, member), argc_(argc), argv_(Value::NewArray(m, argc, argv)) {
260+ object_.SetJsObject (objId);
261+ }
262+ virtual ~JsInvokeMethodMsg () { delete[] argv_; }
263+ // this is a bit of a hack to allow constructing a call with a Buffer
264+ // as an argument.
265+ Value &Argv (int n) { return argv_[n]; }
266+ protected:
267+ virtual void InJs (ObjectMapper *m) {
268+ Nan::MaybeLocal<v8::Object> jsObj =
269+ Nan::To<v8::Object>(object_.ToJs (m));
270+ if (jsObj.IsEmpty ()) {
271+ return Nan::ThrowTypeError (" receiver is not an object" );
272+ }
273+
274+ Nan::MaybeLocal<v8::Object> method = Nan::To<v8::Object>(
275+ Nan::Get (jsObj.ToLocalChecked (), member_.ToJs (m))
276+ .FromMaybe <v8::Value>(Nan::Undefined ())
277+ );
278+ if (method.IsEmpty ()) {
279+ return Nan::ThrowTypeError (" method is not an object" );
280+ }
281+ v8::Local<v8::Value> *argv =
282+ static_cast <v8::Local<v8::Value>*>
283+ (alloca (sizeof (v8::Local<v8::Value>) * argc_));
284+ for (ulong i=0 ; i<argc_; i++) {
285+ new (&argv[i]) v8::Local<v8::Value>;
286+ argv[i] = argv_[i].ToJs (m);
287+ }
288+ Nan::MaybeLocal<v8::Value> result =
289+ Nan::CallAsFunction (method.ToLocalChecked (), jsObj.ToLocalChecked (),
290+ argc_, argv);
291+ if (!result.IsEmpty ()) {
292+ retval_.Set (m, result.ToLocalChecked ());
293+ }
294+ }
295+ };
296+
297+ PHP_METHOD (JsObject, __call) {
298+ zval *member; zval *args;
299+ PARSE_PARAMS (__unset, " z/a" , &member, &args);
300+ convert_to_string (member);
301+ HashTable *arrht = Z_ARRVAL_P (args);
302+ ulong argc = zend_hash_next_free_element (arrht); // maximum index
303+ zval **argv = static_cast <zval**>(alloca (sizeof (zval*) * argc));
304+ for (ulong i=0 ; i<argc; i++) {
305+ zval **z;
306+ if (zend_hash_index_find (arrht, i, (void **) &z)==FAILURE) {
307+ argv[i] = EG (uninitialized_zval_ptr);
308+ } else {
309+ argv[i] = *z;
310+ }
311+ }
312+ JsInvokeMethodMsg msg (obj->channel , obj->id , member, argc, argv);
313+ obj->channel ->Send (&msg);
314+ msg.WaitForResponse ();
315+ THROW_IF_EXCEPTION (" JS exception thrown during __call of \" %*s\" " ,
316+ Z_STRLEN_P (member), Z_STRVAL_P (member));
317+ msg.retval_ .ToPhp (obj->channel , return_value, return_value_ptr TSRMLS_CC);
318+ }
319+
320+
321+
251322
252323/* Use (slightly thunked) versions of the has/read/write property handlers
253324 * for dimensions as well, so that $obj['foo'] acts like $obj->foo. */
@@ -364,6 +435,10 @@ ZEND_END_ARG_INFO()
364435ZEND_BEGIN_ARG_INFO_EX(node_php_jsobject_unset_args, 0 , 0 , 1 )
365436 ZEND_ARG_INFO(0 , member)
366437ZEND_END_ARG_INFO()
438+ ZEND_BEGIN_ARG_INFO_EX(node_php_jsobject_call_args, 0 , 1 /* return by ref*/ , 1 )
439+ ZEND_ARG_INFO(0 , member)
440+ ZEND_ARG_INFO(0 , args)
441+ ZEND_END_ARG_INFO()
367442
368443static const zend_function_entry node_php_jsobject_methods[] = {
369444 PHP_ME (JsObject, __construct, NULL , ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
@@ -375,6 +450,7 @@ static const zend_function_entry node_php_jsobject_methods[] = {
375450 PHP_ME (JsObject, __get, node_php_jsobject_get_args, ZEND_ACC_PUBLIC)
376451 PHP_ME (JsObject, __set, node_php_jsobject_set_args, ZEND_ACC_PUBLIC)
377452 PHP_ME (JsObject, __unset, node_php_jsobject_unset_args, ZEND_ACC_PUBLIC)
453+ PHP_ME (JsObject, __call, node_php_jsobject_call_args, ZEND_ACC_PUBLIC)
378454 ZEND_FE_END
379455};
380456
0 commit comments