Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Version 1.8.5 fully supported, need to check if nothing is broken wit…

…h previous versions now
  • Loading branch information...
commit ae7c1fa79c3efb05f9c477785b09f1d3594abafa 1 parent fd6c532
@christopherobin authored
View
14 package.xml
@@ -12,21 +12,16 @@
<email>crobin@php.net</email>
<active>yes</active>
</lead>
- <date>2010-02-23</date>
+ <date>2011-08-19</date>
<version>
- <release>0.1.4</release><api>0.1.4</api>
+ <release>0.2.0</release><api>0.2.0</api>
</version>
<stability>
- <release>beta</release><api>beta</api>
+ <release>stable</release><api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
- * Fixed bugs 16866, 16876, 16890, 16983:
- * Bug 16866: Returning empty string from static function causes segmentation fault
- * Bug 16876: Empty string as a parameter causes segfault ( same as 16866 )
- * Bug 16890: Variable is cleaned while being used in JS
- * Bug 16983: Problems with registering classes containing __get()
- * Added compatibility with spidermonkey 1.9
+ * Added support for spidermonkey 1.8.5
</notes>
<contents>
<dir name="/">
@@ -47,6 +42,7 @@
<file name="tests/bug16876.phpt" role="test"/>
<file name="tests/bug16890.phpt" role="test"/>
<file name="tests/bug16983.phpt" role="test"/>
+ <file name="tests/bug22838.phpt" role="test"/>
</dir>
</contents>
<dependencies>
View
10 php_spidermonkey.h
@@ -60,6 +60,15 @@ ZEND_END_MODULE_GLOBALS(spidermonkey)
#define SPIDERMONKEY_G(v) (spidermonkey_globals.v)
#endif
+/* those are necessary for threadsafe builds since 1.8.5 */
+#if JS_VERSION >= 180
+#define PHPJS_START(cx) JS_BeginRequest(cx)
+#define PHPJS_END(cx) JS_EndRequest(cx)
+#else
+#define PHPJS_START(cx)
+#define PHPJS_END(cx)
+#endif
+
/* Used by JSContext to store callbacks */
typedef struct _php_callback {
zend_fcall_info fci;
@@ -83,6 +92,7 @@ typedef struct _php_jscontext_object {
HashTable *ec_ht;
/* Javascript related stuff */
JSContext *ct;
+ JSClass global_class;
JSClass script_class;
JSObject *obj;
} php_jscontext_object;
View
54 spidermonkey.c
@@ -116,12 +116,15 @@ static zend_object_value php_jscontext_object_new_ex(zend_class_entry *class_typ
/* the global object doesn't have any zval */
intern->jsref->obj = NULL;
- intern->ct = JS_NewContext(SPIDERMONKEY_G(rt), 8092);
+ intern->ct = JS_NewContext(SPIDERMONKEY_G(rt), 8192);
+ PHPJS_START(intern->ct);
JS_SetContextPrivate(intern->ct, intern);
+
+ memset(&intern->script_class, 0, sizeof(intern->script_class));
/* The script_class is a global object used by PHP to allow function register */
- intern->script_class.name = "PHPclass";
- intern->script_class.flags = JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE;
+ intern->script_class.name = "PHPClass";
+ intern->script_class.flags = JSCLASS_HAS_PRIVATE;
/* Mandatory non-null function pointer members. */
intern->script_class.addProperty = JS_PropertyStub;
@@ -132,36 +135,29 @@ static zend_object_value php_jscontext_object_new_ex(zend_class_entry *class_typ
intern->script_class.finalize = JS_FinalizePHP;
intern->script_class.enumerate = JS_EnumerateStub;
intern->script_class.convert = JS_ConvertStub;
+
+ memcpy(&intern->global_class, &intern->script_class, sizeof(intern->script_class));
+ intern->global_class.name = "PHPGlobalClass";
+ intern->global_class.flags = JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE;
- /* Optionally non-null members start here. */
-#if JS_VERSION < 185
- intern->script_class.getObjectOps = 0;
-#else
- intern->script_class.reserved0 = 0;
-#endif
- intern->script_class.checkAccess = 0;
- intern->script_class.call = 0;
- intern->script_class.construct = 0;
- intern->script_class.xdrObject = 0;
- intern->script_class.hasInstance = 0;
- intern->script_class.mark = 0;
+ /* says that our script runs in global scope */
#if JS_VERSION < 185
- intern->script_class.reserveSlots = 0;
+ JS_SetOptions(intern->ct, JSOPTION_VAROBJFIX);
#else
- intern->script_class.reserved1 = 0;
+ JS_SetOptions(intern->ct, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
#endif
- /* says that our script runs in global scope */
- JS_SetOptions(intern->ct, JSOPTION_VAROBJFIX);
-
/* set the error callback */
JS_SetErrorReporter(intern->ct, reportError);
+ /* use the latest javascript version */
+ JS_SetVersion(intern->ct, JSVERSION_LATEST);
+
/* create global object for execution */
#if JS_VERSION < 185
intern->obj = JS_NewObject(intern->ct, &intern->script_class, NULL, NULL);
#else
- intern->obj = JS_NewGlobalObject(intern->ct, &intern->script_class);
+ intern->obj = JS_NewCompartmentAndGlobalObject(intern->ct, &intern->global_class, NULL);
#endif
/* store pointer to HashTable */
@@ -176,6 +172,7 @@ static zend_object_value php_jscontext_object_new_ex(zend_class_entry *class_typ
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_jscontext_object_free_storage, NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) &jscontext_object_handlers;
+ PHPJS_END(intern->ct);
return retval;
}
@@ -270,6 +267,8 @@ PHP_MINFO_FUNCTION(spidermonkey)
void _jsval_to_zval(zval *return_value, JSContext *ctx, jsval *jval, php_jsparent *parent TSRMLS_DC)
{
jsval rval;
+
+ PHPJS_START(ctx);
rval = *jval;
@@ -307,8 +306,8 @@ void _jsval_to_zval(zval *return_value, JSContext *ctx, jsval *jval, php_jsparen
#else
/* because version 1.8.5 supports unicode, we must encode strings */
char *txt = JS_EncodeString(ctx, str);
- REVAL_STRING(txt, strlen(txt), 1);
- JS_Free(txt);
+ RETVAL_STRINGL(txt, strlen(txt), 1);
+ JS_free(ctx, txt);
#endif
}
else
@@ -350,6 +349,7 @@ void _jsval_to_zval(zval *return_value, JSContext *ctx, jsval *jval, php_jsparen
/* your shouldn't be able to reference the global object */
if (obj == JS_GetGlobalObject(ctx)) {
+ PHPJS_END(ctx);
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Trying to reference global object", 0 TSRMLS_CC);
return;
}
@@ -415,7 +415,7 @@ void _jsval_to_zval(zval *return_value, JSContext *ctx, jsval *jval, php_jsparen
zval_ptr_dtor(&fval);
}
#if JS_VERSION >= 185
- JS_Free(name);
+ JS_free(ctx, name);
#endif
}
}
@@ -432,6 +432,8 @@ void _jsval_to_zval(zval *return_value, JSContext *ctx, jsval *jval, php_jsparen
}
else /* something is wrong */
RETVAL_FALSE;
+
+ PHPJS_END(ctx);
}
/* convert a given jsval in a context to a zval, for PHP access */
@@ -446,8 +448,11 @@ void zval_to_jsval(zval *val, JSContext *ctx, jsval *jval TSRMLS_DC)
php_jsobject_ref *jsref;
php_stream *stream;
+ PHPJS_START(ctx);
+
if (val == NULL) {
*jval = JSVAL_NULL;
+ PHPJS_END(ctx);
return;
}
@@ -613,6 +618,7 @@ void zval_to_jsval(zval *val, JSContext *ctx, jsval *jval TSRMLS_DC)
*jval = JSVAL_VOID;
break;
}
+ PHPJS_END(ctx);
}
/*
View
15 spidermonkey_context.c
@@ -42,6 +42,8 @@ PHP_METHOD(JSContext, registerFunction)
/* retrieve this class from the store */
intern = (php_jscontext_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ PHPJS_START(intern->ct);
Z_ADDREF_P(callback.fci.function_name);
@@ -54,7 +56,8 @@ PHP_METHOD(JSContext, registerFunction)
zend_hash_add(intern->jsref->ht, name, name_len, &callback, sizeof(callback), NULL);
JS_DefineFunction(intern->ct, intern->obj, name, generic_call, 1, 0);
-
+
+ PHPJS_END(intern->ct);
}
/* }}} */
@@ -75,11 +78,14 @@ PHP_METHOD(JSContext, registerClass)
/* retrieve this class from the store */
intern = (php_jscontext_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ PHPJS_START(intern->ct);
if (class_name_len) {
zend_class_entry **pce;
if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
+ PHPJS_END(intern->ct);
zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s doesn't exists !", class_name);
return;
}
@@ -98,6 +104,7 @@ PHP_METHOD(JSContext, registerClass)
JS_DefineFunction(intern->ct, intern->obj, class_name, generic_constructor, 1, 0);
}
+ PHPJS_END(intern->ct);
}
/* }}} */
@@ -142,6 +149,8 @@ PHP_METHOD(JSContext, evaluateScript)
intern = (php_jscontext_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
+ PHPJS_START(intern->ct);
+
if (JS_EvaluateScript(intern->ct, intern->obj, script, script_len, script_name, 0, &rval) == JS_TRUE)
{
if (rval != 0)
@@ -156,8 +165,10 @@ PHP_METHOD(JSContext, evaluateScript)
}
else
{
- RETURN_FALSE;
+ RETVAL_FALSE;
}
+
+ PHPJS_END(intern->ct);
}
/* }}} */
View
55 spidermonkey_external.c
@@ -35,12 +35,16 @@ void reportError(JSContext *cx, const char *message, JSErrorReport *report)
void php_jsobject_set_property(JSContext *ctx, JSObject *obj, char *property_name, zval *val TSRMLS_DC)
{
jsval jval;
+
+ PHPJS_START(ctx);
/* first convert zval to jsval */
zval_to_jsval(val, ctx, &jval TSRMLS_CC);
/* no ref behavior, just set a property */
JS_SetProperty(ctx, obj, property_name, &jval);
+
+ PHPJS_END(ctx);
}
/* all function calls are mapped through this unique function */
@@ -53,6 +57,7 @@ JSBool generic_call(JSContext *cx, uintN argc, jsval *vp)
TSRMLS_FETCH();
JSFunction *func;
JSString *jfunc_name;
+ JSClass *class;
char *func_name;
zval ***params, *retval_ptr = NULL;
php_callback *callback;
@@ -76,8 +81,13 @@ JSBool generic_call(JSContext *cx, uintN argc, jsval *vp)
#endif
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
-
- if ((jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL)) == 0)
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
+
+ if ((jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, class, NULL)) == 0)
{
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Failed to retrieve function table", 0 TSRMLS_CC);
}
@@ -89,7 +99,7 @@ JSBool generic_call(JSContext *cx, uintN argc, jsval *vp)
/* free function name */
#if JS_VERSION >= 185
- JS_Free(func_name);
+ JS_free(cx, func_name);
#endif
/* ready parameters */
@@ -157,12 +167,10 @@ JSBool generic_constructor(JSContext *cx, uintN argc, jsval *vp)
#if JS_VERSION < 185
if (!JS_IsConstructing(cx))
-#else
- if (!JS_IsConstructing(cx, vp))
-#endif
{
return JS_FALSE;
}
+#endif
/* first retrieve class name */
class = JS_ValueToFunction(cx, ((argv)[-2]));
@@ -183,7 +191,7 @@ JSBool generic_constructor(JSContext *cx, uintN argc, jsval *vp)
/* free class name */
#if JS_VERSION >= 185
- JS_Free(class_name);
+ JS_free(cx, class_name);
#endif
/* retrieve pointer to ce */
@@ -302,9 +310,16 @@ JSBool JS_PropertySetterPHP(JSContext *cx, JSObject *obj, jsid id, JSBool strict
TSRMLS_FETCH();
php_jsobject_ref *jsref;
php_jscontext_object *intern;
+ JSClass *class;
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
- jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL);
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
+
+ jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, class, NULL);
if (jsref != NULL)
{
@@ -313,10 +328,14 @@ JSBool JS_PropertySetterPHP(JSContext *cx, JSObject *obj, jsid id, JSBool strict
char *prop_name;
zval *val;
- str = JS_ValueToString(cx, id);
#if JS_VERSION < 185
+ str = JS_ValueToString(cx, id);
prop_name = JS_GetStringBytes(str);
#else
+ /* 1.8.5 uses reals jsid for id, we need to convert it */
+ jsval rid;
+ JS_IdToValue(cx, id, &rid);
+ str = JS_ValueToString(cx, rid);
/* because version 1.8.5 supports unicode, we must encode strings */
prop_name = JS_EncodeString(cx, str);
#endif
@@ -329,7 +348,7 @@ JSBool JS_PropertySetterPHP(JSContext *cx, JSObject *obj, jsid id, JSBool strict
/* free prop name */
#if JS_VERSION >= 185
- JS_Free(prop_name);
+ JS_free(cx, prop_name);
#endif
}
}
@@ -346,8 +365,14 @@ JSBool JS_PropertyGetterPHP(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
TSRMLS_FETCH();
php_jsobject_ref *jsref;
php_jscontext_object *intern;
+ JSClass *class;
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL);
if (jsref != NULL) {
@@ -357,10 +382,14 @@ JSBool JS_PropertyGetterPHP(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
zval *val = NULL;
JSBool has_property;
- str = JS_ValueToString(cx, id);
#if JS_VERSION < 185
+ str = JS_ValueToString(cx, id);
prop_name = JS_GetStringBytes(str);
#else
+ /* 1.8.5 uses reals jsid for id, we need to convert it */
+ jsval rid;
+ JS_IdToValue(cx, id, &rid);
+ str = JS_ValueToString(cx, rid);
/* because version 1.8.5 supports unicode, we must encode strings */
prop_name = JS_EncodeString(cx, str);
#endif
@@ -370,7 +399,7 @@ JSBool JS_PropertyGetterPHP(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
if (JS_LookupProperty(cx, obj, prop_name, vp) == JS_TRUE) {
/* free prop name */
#if JS_VERSION >= 185
- JS_Free(prop_name);
+ JS_free(cx, prop_name);
#endif
return JS_TRUE;
}
@@ -380,7 +409,7 @@ JSBool JS_PropertyGetterPHP(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
/* free prop name */
#if JS_VERSION >= 185
- JS_Free(prop_name);
+ JS_free(cx, prop_name);
#endif
if (val != EG(uninitialized_zval_ptr)) {
View
53 spidermonkey_streams.c
@@ -33,6 +33,7 @@ JSBool js_stream_read(JSContext *cx, uintN argc, jsval *vp)
php_jscontext_object *intern;
php_jsobject_ref *jsref;
php_stream *stream = NULL;
+ JSClass *class;
#if JS_VERSION >= 185
JSObject *obj = JS_THIS_OBJECT(cx, vp);
jsval *argv = JS_ARGV(cx,vp);
@@ -40,7 +41,13 @@ JSBool js_stream_read(JSContext *cx, uintN argc, jsval *vp)
#endif
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
- jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL);
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
+
+ jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, class, NULL);
if (jsref != NULL && jsref->obj != NULL && Z_TYPE_P(jsref->obj) == IS_RESOURCE) {
JSString *jstr;
@@ -96,6 +103,7 @@ JSBool js_stream_getline(JSContext *cx, uintN argc, jsval *vp)
php_jscontext_object *intern;
php_jsobject_ref *jsref;
php_stream *stream = NULL;
+ JSClass *class;
#if JS_VERSION >= 185
JSObject *obj = JS_THIS_OBJECT(cx, vp);
jsval *argv = JS_ARGV(cx,vp);
@@ -104,7 +112,13 @@ JSBool js_stream_getline(JSContext *cx, uintN argc, jsval *vp)
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
- jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL);
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
+
+ jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, class, NULL);
if (jsref != NULL && jsref->obj != NULL && Z_TYPE_P(jsref->obj) == IS_RESOURCE) {
JSString *jstr;
@@ -160,6 +174,7 @@ JSBool js_stream_seek(JSContext *cx, uintN argc, jsval *vp)
php_jscontext_object *intern;
php_jsobject_ref *jsref;
php_stream *stream = NULL;
+ JSClass *class;
#if JS_VERSION >= 185
JSObject *obj = JS_THIS_OBJECT(cx, vp);
jsval *argv = JS_ARGV(cx,vp);
@@ -167,7 +182,13 @@ JSBool js_stream_seek(JSContext *cx, uintN argc, jsval *vp)
#endif
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
- jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL);
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
+
+ jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, class, NULL);
if (jsref != NULL && jsref->obj != NULL && Z_TYPE_P(jsref->obj) == IS_RESOURCE && argc >= 1) {
off_t pos;
@@ -211,6 +232,7 @@ JSBool js_stream_write(JSContext *cx, uintN argc, jsval *vp)
php_jscontext_object *intern;
php_jsobject_ref *jsref;
php_stream *stream = NULL;
+ JSClass *class;
#if JS_VERSION >= 185
JSObject *obj = JS_THIS_OBJECT(cx, vp);
jsval *argv = JS_ARGV(cx,vp);
@@ -218,7 +240,13 @@ JSBool js_stream_write(JSContext *cx, uintN argc, jsval *vp)
#endif
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
- jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL);
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
+
+ jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, class, NULL);
if (jsref != NULL && jsref->obj != NULL && Z_TYPE_P(jsref->obj) == IS_RESOURCE && argc >= 1) {
JSString *jstr;
@@ -235,7 +263,11 @@ JSBool js_stream_write(JSContext *cx, uintN argc, jsval *vp)
jstr = JS_ValueToString(cx, argv[0]);
if (jstr != NULL) {
/* then we retrieve the pointer to the string */
+#if JS_VERSION < 185
char *txt = JS_GetStringBytes(jstr);
+#else
+ char *txt = JS_EncodeString(cx, jstr);
+#endif
if (argc >= 2)
{
buf_len = JSVAL_TO_INT(argv[1]);
@@ -245,6 +277,10 @@ JSBool js_stream_write(JSContext *cx, uintN argc, jsval *vp)
{
nbytes = php_stream_write_string(stream, txt);
}
+
+#if JS_VERSION >= 185
+ JS_free(cx, txt);
+#endif
}
else {
reportError(cx, "Failed to convert type to string", NULL);
@@ -268,6 +304,7 @@ JSBool js_stream_tell(JSContext *cx, uintN argc, jsval *vp)
php_jscontext_object *intern;
php_jsobject_ref *jsref;
php_stream *stream = NULL;
+ JSClass *class;
#if JS_VERSION >= 185
JSObject *obj = JS_THIS_OBJECT(cx, vp);
jsval *argv = JS_ARGV(cx,vp);
@@ -275,7 +312,13 @@ JSBool js_stream_tell(JSContext *cx, uintN argc, jsval *vp)
#endif
intern = (php_jscontext_object*)JS_GetContextPrivate(cx);
- jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, &intern->script_class, NULL);
+ class = &intern->script_class;
+
+ if (obj == intern->obj) {
+ class =&intern->global_class;
+ }
+
+ jsref = (php_jsobject_ref*)JS_GetInstancePrivate(cx, obj, class, NULL);
if (jsref != NULL && jsref->obj != NULL && Z_TYPE_P(jsref->obj) == IS_RESOURCE) {
off_t file_pos;
View
5 tests/bug16890.phpt
@@ -46,8 +46,5 @@ object(stdClass)#2 (4) {
}
object(stdClass)#2 (1) {
["b"]=>
- object(stdClass)#2 (1) {
- ["b"]=>
- *RECURSION*
- }
+ *RECURSION*
}
Please sign in to comment.
Something went wrong with that request. Please try again.