@@ -30,6 +30,7 @@ extern "C" {
3030#include " v8js_v8.h"
3131#include " v8js_exceptions.h"
3232#include " v8js_v8object_class.h"
33+ #include " v8js_object_export.h"
3334#include " v8js_timer.h"
3435
3536#include < functional>
@@ -45,6 +46,9 @@ static zend_class_entry *php_ce_v8js;
4546static zend_object_handlers v8js_object_handlers;
4647/* }}} */
4748
49+ /* Forward declare v8js_methods, actually "static" but not possible in C++ */
50+ extern const zend_function_entry v8js_methods[];
51+
4852typedef struct _v8js_script {
4953 char *name;
5054 v8js_ctx *ctx;
@@ -319,6 +323,10 @@ static void v8js_fatal_error_handler(const char *location, const char *message)
319323}
320324/* }}} */
321325
326+ #define IS_MAGIC_FUNC (mname ) \
327+ ((key_len == sizeof (mname)) && \
328+ !strncasecmp(key, mname, key_len - 1 ))
329+
322330/* {{{ proto void V8Js::__construct([string object_name [, array variables [, array extensions [, bool report_uncaught_exceptions]]])
323331 __construct for V8Js */
324332static PHP_METHOD (V8Js, __construct)
@@ -480,7 +488,78 @@ static PHP_METHOD(V8Js, __construct)
480488 }
481489 }
482490
491+ /* Add pointer to zend object */
492+ php_obj->SetHiddenValue (V8JS_SYM (PHPJS_OBJECT_KEY), v8::External::New (isolate, getThis ()));
493+
494+ /* Export public methods */
495+ zend_function *method_ptr;
496+ char *key = NULL ;
497+ uint key_len;
498+
499+ zend_hash_internal_pointer_reset_ex (&c->std .ce ->function_table , &pos);
500+ for (;; zend_hash_move_forward_ex (&c->std .ce ->function_table , &pos)) {
501+ if (zend_hash_get_current_key_ex (&c->std .ce ->function_table , &key, &key_len, &index, 0 , &pos) != HASH_KEY_IS_STRING ||
502+ zend_hash_get_current_data_ex (&c->std .ce ->function_table , (void **) &method_ptr, &pos) == FAILURE
503+ ) {
504+ break ;
505+ }
483506
507+ if ((method_ptr->common .fn_flags & ZEND_ACC_PUBLIC) == 0 ) {
508+ /* Allow only public methods */
509+ continue ;
510+ }
511+
512+ if ((method_ptr->common .fn_flags & (ZEND_ACC_CTOR|ZEND_ACC_DTOR|ZEND_ACC_CLONE)) != 0 ) {
513+ /* no __construct, __destruct(), or __clone() functions */
514+ continue ;
515+ }
516+
517+ /* hide (do not export) other PHP magic functions */
518+ if (IS_MAGIC_FUNC (ZEND_CALLSTATIC_FUNC_NAME) ||
519+ IS_MAGIC_FUNC (ZEND_SLEEP_FUNC_NAME) ||
520+ IS_MAGIC_FUNC (ZEND_WAKEUP_FUNC_NAME) ||
521+ IS_MAGIC_FUNC (ZEND_SET_STATE_FUNC_NAME) ||
522+ IS_MAGIC_FUNC (ZEND_GET_FUNC_NAME) ||
523+ IS_MAGIC_FUNC (ZEND_SET_FUNC_NAME) ||
524+ IS_MAGIC_FUNC (ZEND_UNSET_FUNC_NAME) ||
525+ IS_MAGIC_FUNC (ZEND_CALL_FUNC_NAME) ||
526+ IS_MAGIC_FUNC (ZEND_INVOKE_FUNC_NAME) ||
527+ IS_MAGIC_FUNC (ZEND_TOSTRING_FUNC_NAME) ||
528+ IS_MAGIC_FUNC (ZEND_ISSET_FUNC_NAME)) {
529+ continue ;
530+ }
531+
532+ const zend_function_entry *fe;
533+ for (fe = v8js_methods; fe->fname ; fe ++) {
534+ if (strcmp (fe->fname , method_ptr->common .function_name ) == 0 ) {
535+ break ;
536+ }
537+ }
538+
539+ if (fe->fname ) {
540+ /* Method belongs to \V8Js class itself, never export to V8, even if
541+ * it is overriden in a derived class. */
542+ continue ;
543+ }
544+
545+ v8::Local<v8::String> method_name = V8JS_STR (method_ptr->common .function_name );
546+ v8::Local<v8::FunctionTemplate> ft;
547+
548+ try {
549+ ft = v8::Local<v8::FunctionTemplate>::New
550+ (isolate, c->method_tmpls .at (method_ptr));
551+ }
552+ catch (const std::out_of_range &) {
553+ ft = v8::FunctionTemplate::New (isolate, v8js_php_callback,
554+ v8::External::New ((isolate), method_ptr));
555+ // @fixme add/check Signature v8::Signature::New((isolate), tmpl));
556+ v8js_tmpl_t *persistent_ft = &c->method_tmpls [method_ptr];
557+ persistent_ft->Reset (isolate, ft);
558+ }
559+
560+
561+ php_obj->ForceSet (method_name, ft->GetFunction ());
562+ }
484563}
485564/* }}} */
486565
@@ -1056,7 +1135,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_setmemorylimit, 0, 0, 1)
10561135ZEND_END_ARG_INFO()
10571136
10581137
1059- static const zend_function_entry v8js_methods[] = { /* {{{ */
1138+ const zend_function_entry v8js_methods[] = { /* {{{ */
10601139 PHP_ME (V8Js, __construct, arginfo_v8js_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
10611140 PHP_ME (V8Js, __sleep, arginfo_v8js_sleep, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
10621141 PHP_ME (V8Js, __wakeup, arginfo_v8js_sleep, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
@@ -1107,7 +1186,7 @@ static void v8js_unset_property(zval *object, zval *member ZEND_HASH_KEY_DC TSRM
11071186 /* Global PHP JS object */
11081187 v8::Local<v8::String> object_name_js = v8::Local<v8::String>::New (isolate, c->object_name );
11091188 v8::Local<v8::Object> jsobj = V8JS_GLOBAL (isolate)->Get (object_name_js)->ToObject ();
1110-
1189+
11111190 /* Delete value from PHP JS object */
11121191 jsobj->Delete (V8JS_SYML (Z_STRVAL_P (member), Z_STRLEN_P (member)));
11131192
0 commit comments