@@ -267,30 +267,40 @@ PHP_METHOD(JsObject, __unset) {
267267 TRACE (" <" );
268268}
269269
270- class JsInvokeMethodMsg : public MessageToJs {
270+ class JsInvokeMsg : public MessageToJs {
271271 Value object_;
272272 Value member_;
273273 ulong argc_;
274274 Value *argv_;
275275 public:
276- JsInvokeMethodMsg (ObjectMapper *m, objid_t objId, zval *member, ulong argc, zval **argv TSRMLS_DC)
276+ JsInvokeMsg (ObjectMapper *m, objid_t objId, zval *member, ulong argc, zval **argv TSRMLS_DC)
277277 : MessageToJs(m), object_(), member_(m, member TSRMLS_CC), argc_(argc), argv_(Value::NewArray(m, argc, argv TSRMLS_CC)) {
278278 object_.SetJsObject (objId);
279279 }
280- virtual ~JsInvokeMethodMsg () { delete[] argv_; }
280+ virtual ~JsInvokeMsg () { delete[] argv_; }
281281 protected:
282282 virtual void InJs (ObjectMapper *m) {
283- TRACE (" > JsInvokeMethodMsg " );
283+ TRACE (" > JsInvokeMsg " );
284284 Nan::MaybeLocal<v8::Object> jsObj =
285285 Nan::To<v8::Object>(object_.ToJs (m));
286286 if (jsObj.IsEmpty ()) {
287287 return Nan::ThrowTypeError (" receiver is not an object" );
288288 }
289289
290- Nan::MaybeLocal<v8::Object> method = Nan::To<v8::Object>(
291- Nan::Get (jsObj.ToLocalChecked (), member_.ToJs (m))
292- .FromMaybe <v8::Value>(Nan::Undefined ())
293- );
290+ v8::Local<v8::Value> member = member_.ToJs (m);
291+ Nan::MaybeLocal<v8::Object> method;
292+ if (member->IsNull ()) {
293+ // invoke function, not method.
294+ method = jsObj;
295+ // should be null, but https://github.com/nodejs/nan/issues/497
296+ // doesn't let us pass null to functions yet.
297+ jsObj = Nan::MakeMaybe (Nan::New<v8::Object>());
298+ } else {
299+ method = Nan::To<v8::Object>(
300+ Nan::Get (jsObj.ToLocalChecked (), member)
301+ .FromMaybe <v8::Value>(Nan::Undefined ())
302+ );
303+ }
294304 if (method.IsEmpty ()) {
295305 return Nan::ThrowTypeError (" method is not an object" );
296306 }
@@ -307,7 +317,7 @@ class JsInvokeMethodMsg : public MessageToJs {
307317 if (!result.IsEmpty ()) {
308318 retval_.Set (m, result.ToLocalChecked ());
309319 }
310- TRACE (" < JsInvokeMethodMsg " );
320+ TRACE (" < JsInvokeMsg " );
311321 }
312322};
313323
@@ -327,7 +337,7 @@ PHP_METHOD(JsObject, __call) {
327337 argv[i] = *z;
328338 }
329339 }
330- JsInvokeMethodMsg msg (obj->channel , obj->id , member, argc, argv TSRMLS_CC);
340+ JsInvokeMsg msg (obj->channel , obj->id , member, argc, argv TSRMLS_CC);
331341 obj->channel ->Send (&msg);
332342 msg.WaitForResponse ();
333343 THROW_IF_EXCEPTION (" JS exception thrown during __call of \" %*s\" " ,
@@ -336,7 +346,26 @@ PHP_METHOD(JsObject, __call) {
336346 TRACE (" <" );
337347}
338348
339-
349+ PHP_METHOD (JsObject, __invoke) {
350+ TRACE (" >" );
351+ node_php_jsobject *obj = (node_php_jsobject *)
352+ zend_object_store_get_object (this_ptr TSRMLS_CC);
353+ zval member; INIT_ZVAL (member);
354+ int argc = ZEND_NUM_ARGS ();
355+ zval **argv = (zval**) safe_emalloc (argc, sizeof (*argv), 0 );
356+ if (argc > 0 && zend_get_parameters_array (ht, argc, argv) == FAILURE) {
357+ efree (argv);
358+ zend_throw_exception (zend_exception_get_default (TSRMLS_C), " bad args to __invoke" , 0 TSRMLS_CC);
359+ return ;
360+ }
361+ JsInvokeMsg msg (obj->channel , obj->id , &member, argc, argv TSRMLS_CC);
362+ efree (argv);
363+ obj->channel ->Send (&msg);
364+ msg.WaitForResponse ();
365+ THROW_IF_EXCEPTION (" JS exception thrown during __invoke" );
366+ msg.retval_ .ToPhp (obj->channel , return_value, return_value_ptr TSRMLS_CC);
367+ TRACE (" <" );
368+ }
340369
341370
342371/* Use (slightly thunked) versions of the has/read/write property handlers
@@ -482,6 +511,7 @@ static const zend_function_entry node_php_jsobject_methods[] = {
482511 PHP_ME (JsObject, __set, node_php_jsobject_set_args, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
483512 PHP_ME (JsObject, __unset, node_php_jsobject_unset_args, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
484513 PHP_ME (JsObject, __call, node_php_jsobject_call_args, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
514+ PHP_ME (JsObject, __invoke, NULL , ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
485515 ZEND_FE_END
486516};
487517
0 commit comments