@@ -29,7 +29,7 @@ v8::Local<v8::Function> php_v8_value_get_function_local(v8::Isolate *isolate, ph
2929 return v8::Local<v8::Function>::Cast (php_v8_value_get_value_local (isolate, php_v8_value));
3030};
3131
32- bool php_v8_function_unpack_args (zval* arguments_zv, zval *this_ptr , int arg_position, v8::Isolate *isolate, int *argc, v8::Local<v8::Value> **argv) {
32+ bool php_v8_function_unpack_args (zval *arguments_zv , int arg_position, v8::Isolate *isolate, int *argc, v8::Local<v8::Value> **argv) {
3333 if (NULL == arguments_zv || zend_hash_num_elements (Z_ARRVAL_P (arguments_zv)) < 1 ) {
3434 return true ;
3535 }
@@ -49,11 +49,17 @@ bool php_v8_function_unpack_args(zval* arguments_zv, zval *this_ptr, int arg_pos
4949
5050 char *exception_message;
5151
52+ #if PHP_VERSION_ID >= 70100
53+ zend_string *ce_name = zend_get_executed_scope ()->name ;
54+ #else
55+ zend_string *ce_name = EG (scope)->name ;
56+ #endif
57+
5258 ZEND_HASH_FOREACH_VAL (myht, pzval) {
5359 if (Z_TYPE_P (pzval) != IS_OBJECT) {
5460 zend_throw_error (zend_ce_type_error,
5561 " Argument %d passed to %s::%s() should be array of \\ V8\\ Value objects, %s given at %d offset" ,
56- arg_position, ZSTR_VAL (Z_OBJCE_P (this_ptr)-> name ), get_active_function_name (),
62+ arg_position, ZSTR_VAL (ce_name ), get_active_function_name (),
5763 zend_zval_type_name (pzval), i);
5864
5965 has_error = true ;
@@ -63,7 +69,7 @@ bool php_v8_function_unpack_args(zval* arguments_zv, zval *this_ptr, int arg_pos
6369 if (!instanceof_function (Z_OBJCE_P (pzval), php_v8_value_class_entry)) {
6470 zend_throw_error (zend_ce_type_error,
6571 " Argument %d passed to %s::%s() should be array of \\ V8\\ Value objects, instance of %s given at %d offset" ,
66- arg_position, ZSTR_VAL (Z_OBJCE_P (this_ptr)-> name ), get_active_function_name (),
72+ arg_position, ZSTR_VAL (ce_name ), get_active_function_name (),
6773 ZSTR_VAL (Z_OBJCE_P (pzval)->name ), i);
6874
6975 has_error = true ;
@@ -77,7 +83,7 @@ bool php_v8_function_unpack_args(zval* arguments_zv, zval *this_ptr, int arg_pos
7783 // less confusing exception message
7884 if (NULL == php_v8_tmp_data->persistent || php_v8_tmp_data->persistent ->IsEmpty ()) {
7985 spprintf (&exception_message, 0 , PHP_V8_EMPTY_VALUE_MSG " : argument %d passed to %s::%s() at %d offset" ,
80- arg_position, ZSTR_VAL (Z_OBJCE_P (this_ptr)-> name ), get_active_function_name (), i);
86+ arg_position, ZSTR_VAL (ce_name ), get_active_function_name (), i);
8187
8288 PHP_V8_THROW_EXCEPTION (exception_message);
8389
@@ -89,7 +95,7 @@ bool php_v8_function_unpack_args(zval* arguments_zv, zval *this_ptr, int arg_pos
8995 if (NULL == php_v8_tmp_data->php_v8_isolate || isolate != php_v8_tmp_data->php_v8_isolate ->isolate ) {
9096 spprintf (&exception_message, 0 ,
9197 PHP_V8_ISOLATES_MISMATCH_MSG " : argument %d passed to %s::%s() at %d offset" ,
92- arg_position, ZSTR_VAL (Z_OBJCE_P (this_ptr)-> name ), get_active_function_name (), i);
98+ arg_position, ZSTR_VAL (ce_name ), get_active_function_name (), i);
9399
94100 PHP_V8_THROW_EXCEPTION (exception_message);
95101
@@ -112,6 +118,184 @@ bool php_v8_function_unpack_args(zval* arguments_zv, zval *this_ptr, int arg_pos
112118 return true ;
113119}
114120
121+ bool php_v8_function_unpack_string_args (zval* arguments_zv, int arg_position, v8::Isolate *isolate, int *argc, v8::Local<v8::String> **argv) {
122+ if (NULL == arguments_zv || zend_hash_num_elements (Z_ARRVAL_P (arguments_zv)) < 1 ) {
123+ return true ;
124+ }
125+
126+ php_v8_value_t *php_v8_tmp_data;
127+
128+ int i = 0 ;
129+ bool has_error = false ;
130+
131+ HashTable *myht;
132+ zval *pzval;
133+
134+ *argc = zend_hash_num_elements (Z_ARRVAL_P (arguments_zv));
135+ *argv = (v8::Local<v8::String> *) ecalloc (static_cast <size_t >(*argc), sizeof (*argv));
136+
137+ myht = Z_ARRVAL_P (arguments_zv);
138+
139+ char *exception_message;
140+
141+ #if PHP_VERSION_ID >= 70100
142+ zend_string *ce_name = zend_get_executed_scope ()->name ;
143+ #else
144+ zend_string *ce_name = EG (scope)->name ;
145+ #endif
146+
147+ ZEND_HASH_FOREACH_VAL (myht, pzval) {
148+ if (Z_TYPE_P (pzval) != IS_OBJECT) {
149+ zend_throw_error (zend_ce_type_error,
150+ " Argument %d passed to %s::%s() should be array of \\ V8\\ StringValue objects, %s given at %d offset" ,
151+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (),
152+ zend_zval_type_name (pzval), i);
153+
154+ has_error = true ;
155+ break ;
156+ }
157+
158+ if (!instanceof_function (Z_OBJCE_P (pzval), php_v8_string_class_entry)) {
159+ zend_throw_error (zend_ce_type_error,
160+ " Argument %d passed to %s::%s() should be array of \\ V8\\ StringValue, instance of %s given at %d offset" ,
161+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (),
162+ ZSTR_VAL (Z_OBJCE_P (pzval)->name ), i);
163+
164+ has_error = true ;
165+ break ;
166+ }
167+
168+ php_v8_tmp_data = PHP_V8_VALUE_FETCH (pzval);
169+
170+ // NOTE: check for emptiness may be considered redundant while we may catch the fact that value was not properly
171+ // constructed by checking isolates mismatch, but this check serves for user-friendly purposes to throw
172+ // less confusing exception message
173+ if (NULL == php_v8_tmp_data->persistent || php_v8_tmp_data->persistent ->IsEmpty ()) {
174+ spprintf (&exception_message, 0 , PHP_V8_EMPTY_VALUE_MSG " : argument %d passed to %s::%s() at %d offset" ,
175+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (), i);
176+
177+ PHP_V8_THROW_EXCEPTION (exception_message);
178+
179+ efree (exception_message);
180+ has_error = true ;
181+ break ;
182+ }
183+
184+ if (NULL == php_v8_tmp_data->php_v8_isolate || isolate != php_v8_tmp_data->php_v8_isolate ->isolate ) {
185+ spprintf (&exception_message, 0 ,
186+ PHP_V8_ISOLATES_MISMATCH_MSG " : argument %d passed to %s::%s() at %d offset" ,
187+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (), i);
188+
189+ PHP_V8_THROW_EXCEPTION (exception_message);
190+
191+ efree (exception_message);
192+ has_error = true ;
193+ break ;
194+ }
195+
196+ (*argv)[i++] = php_v8_value_get_string_local (isolate, php_v8_tmp_data);
197+ } ZEND_HASH_FOREACH_END ();
198+
199+ if (has_error) {
200+ efree (*argv);
201+ *argv = NULL ;
202+ *argc = 0 ;
203+
204+ return false ;
205+ }
206+
207+ return true ;
208+ }
209+
210+ bool php_v8_function_unpack_object_args (zval* arguments_zv, int arg_position, v8::Isolate *isolate, int *argc, v8::Local<v8::Object> **argv) {
211+ if (NULL == arguments_zv || zend_hash_num_elements (Z_ARRVAL_P (arguments_zv)) < 1 ) {
212+ return true ;
213+ }
214+
215+ php_v8_value_t *php_v8_tmp_data;
216+
217+ int i = 0 ;
218+ bool has_error = false ;
219+
220+ HashTable *myht;
221+ zval *pzval;
222+
223+ *argc = zend_hash_num_elements (Z_ARRVAL_P (arguments_zv));
224+ *argv = (v8::Local<v8::Object> *) ecalloc (static_cast <size_t >(*argc), sizeof (*argv));
225+
226+ myht = Z_ARRVAL_P (arguments_zv);
227+
228+ char *exception_message;
229+
230+ #if PHP_VERSION_ID >= 70100
231+ zend_string *ce_name = zend_get_executed_scope ()->name ;
232+ #else
233+ zend_string *ce_name = EG (scope)->name ;
234+ #endif
235+
236+ ZEND_HASH_FOREACH_VAL (myht, pzval) {
237+ if (Z_TYPE_P (pzval) != IS_OBJECT) {
238+ zend_throw_error (zend_ce_type_error,
239+ " Argument %d passed to %s::%s() should be array of \\ V8\\ ObjectValue objects, %s given at %d offset" ,
240+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (),
241+ zend_zval_type_name (pzval), i);
242+
243+ has_error = true ;
244+ break ;
245+ }
246+
247+ if (!instanceof_function (Z_OBJCE_P (pzval), php_v8_object_class_entry)) {
248+ zend_throw_error (zend_ce_type_error,
249+ " Argument %d passed to %s::%s() should be array of \\ V8\\ ObjectValue, instance of %s given at %d offset" ,
250+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (),
251+ ZSTR_VAL (Z_OBJCE_P (pzval)->name ), i);
252+
253+ has_error = true ;
254+ break ;
255+ }
256+
257+ php_v8_tmp_data = PHP_V8_VALUE_FETCH (pzval);
258+
259+ // NOTE: check for emptiness may be considered redundant while we may catch the fact that value was not properly
260+ // constructed by checking isolates mismatch, but this check serves for user-friendly purposes to throw
261+ // less confusing exception message
262+ if (NULL == php_v8_tmp_data->persistent || php_v8_tmp_data->persistent ->IsEmpty ()) {
263+ spprintf (&exception_message, 0 , PHP_V8_EMPTY_VALUE_MSG " : argument %d passed to %s::%s() at %d offset" ,
264+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (), i);
265+
266+ PHP_V8_THROW_EXCEPTION (exception_message);
267+
268+ efree (exception_message);
269+ has_error = true ;
270+ break ;
271+ }
272+
273+ if (NULL == php_v8_tmp_data->php_v8_isolate || isolate != php_v8_tmp_data->php_v8_isolate ->isolate ) {
274+ spprintf (&exception_message, 0 ,
275+ PHP_V8_ISOLATES_MISMATCH_MSG " : argument %d passed to %s::%s() at %d offset" ,
276+ arg_position, ZSTR_VAL (ce_name), get_active_function_name (), i);
277+
278+ PHP_V8_THROW_EXCEPTION (exception_message);
279+
280+ efree (exception_message);
281+ has_error = true ;
282+ break ;
283+ }
284+
285+ (*argv)[i++] = php_v8_value_get_object_local (isolate, php_v8_tmp_data);
286+ } ZEND_HASH_FOREACH_END ();
287+
288+ if (has_error) {
289+ efree (*argv);
290+ *argv = NULL ;
291+ *argc = 0 ;
292+
293+ return false ;
294+ }
295+
296+ return true ;
297+ }
298+
115299
116300static PHP_METHOD (V8Function, __construct) {
117301 zval rv;
@@ -194,7 +378,7 @@ static PHP_METHOD(V8Function, NewInstance) {
194378 PHP_V8_ENTER_STORED_ISOLATE (php_v8_context);
195379 PHP_V8_ENTER_CONTEXT (php_v8_context);
196380
197- if (!php_v8_function_unpack_args (arguments_zv, getThis (), 2 , isolate, &argc, &argv)) {
381+ if (!php_v8_function_unpack_args (arguments_zv, 2 , isolate, &argc, &argv)) {
198382 return ;
199383 }
200384
@@ -239,7 +423,7 @@ static PHP_METHOD(V8Function, Call) {
239423 PHP_V8_ENTER_STORED_ISOLATE (php_v8_context);
240424 PHP_V8_ENTER_CONTEXT (php_v8_context);
241425
242- if (!php_v8_function_unpack_args (arguments_zv, getThis (), 3 , isolate, &argc, &argv)) {
426+ if (!php_v8_function_unpack_args (arguments_zv, 3 , isolate, &argc, &argv)) {
243427 return ;
244428 }
245429
0 commit comments