Browse Source

Add setMemoryLimit & setTimeLimit setter methods

Stefan Siegl 10 years ago
parent
commit
3a1f3e5237
4 changed files with 120 additions and 0 deletions
  1. 5 0
      php_v8js_macros.h
  2. 32 0
      tests/set_memory_limit_basic.phpt
  3. 29 0
      tests/set_time_limit_basic.phpt
  4. 54 0
      v8js.cc

+ 5 - 0
php_v8js_macros.h

@@ -157,9 +157,14 @@ struct php_v8js_ctx {
   zval *pending_exception;
   int in_execution;
   v8::Isolate *isolate;
+
+  long time_limit;
   bool time_limit_hit;
+  long memory_limit;
   bool memory_limit_hit;
+
   v8::Persistent<v8::FunctionTemplate> global_template;
+
   zval *module_loader;
   std::vector<char *> modules_stack;
   std::vector<char *> modules_base;

+ 32 - 0
tests/set_memory_limit_basic.phpt

@@ -0,0 +1,32 @@
+--TEST--
+Test V8::setMemoryLimit() : Memory limit can be set on V8Js object
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--FILE--
+<?php
+$JS = <<< EOT
+var text = "abcdefghijklmnopqrstuvwyxz0123456789";
+var memory = "";
+for (var i = 0; i < 100; ++i) {
+    for (var j = 0; j < 10000; ++j) {
+        memory += text;
+    }
+    sleep(0);
+}
+EOT;
+
+$v8 = new V8Js();
+$v8->setMemoryLimit(10000000);
+
+try {
+    var_dump($v8->executeString($JS, 'basic.js'));
+} catch (V8JsMemoryLimitException $e) {
+    print get_class($e); print PHP_EOL;
+    print $e->getMessage(); print PHP_EOL;
+}
+?>
+===EOF===
+--EXPECT--
+V8JsMemoryLimitException
+Script memory limit of 10000000 bytes exceeded
+===EOF===

+ 29 - 0
tests/set_time_limit_basic.phpt

@@ -0,0 +1,29 @@
+--TEST--
+Test V8::setTimeLimit() : Time limit can be set on V8Js object
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--FILE--
+<?php
+
+$JS = <<< EOT
+var text = "abcdefghijklmnopqrstuvwyxz0123456789";
+for (var i = 0; i < 10000000; ++i) {
+    var encoded = encodeURI(text);
+}
+EOT;
+
+$v8 = new V8Js();
+$v8->setTimeLimit(100);
+
+try {
+    var_dump($v8->executeString($JS, 'basic.js'));
+} catch (V8JsTimeLimitException $e) {
+    print get_class($e); print PHP_EOL;
+    print $e->getMessage(); print PHP_EOL;
+}
+?>
+===EOF===
+--EXPECT--
+V8JsTimeLimitException
+Script time limit of 100 milliseconds exceeded
+===EOF===

+ 54 - 0
v8js.cc

@@ -914,8 +914,12 @@ static PHP_METHOD(V8Js, __construct)
 	c->in_execution = 0;
 	c->isolate = v8::Isolate::New();
 	c->isolate->SetData(0, c);
+
+	c->time_limit = 0;
 	c->time_limit_hit = false;
+	c->memory_limit = 0;
 	c->memory_limit_hit = false;
+
 	c->module_loader = NULL;
 
 	/* Include extensions used by this context */
@@ -1207,6 +1211,14 @@ static void php_v8js_execute_script(zval *this_ptr, php_v8js_script *res, long f
 		}
 	}
 
+	if (!c->in_execution && time_limit == 0) {
+		time_limit = c->time_limit;
+	}
+
+	if (!c->in_execution && memory_limit == 0) {
+		memory_limit = c->memory_limit;
+	}
+
 	if (time_limit > 0 || memory_limit > 0) {
 		// If timer thread is not running then start it
 		if (!V8JSG(timer_thread)) {
@@ -1511,6 +1523,38 @@ static PHP_METHOD(V8Js, setModuleLoader)
 }
 /* }}} */
 
+/* {{{ proto void V8Js::setTimeLimit(int time_limit)
+ */
+static PHP_METHOD(V8Js, setTimeLimit)
+{
+	php_v8js_ctx *c;
+	long time_limit = 0;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &time_limit) == FAILURE) {
+		return;
+	}
+
+	c = (php_v8js_ctx *) zend_object_store_get_object(getThis() TSRMLS_CC);
+	c->time_limit = time_limit;
+}
+/* }}} */
+
+/* {{{ proto void V8Js::setMemoryLimit(int memory_limit)
+ */
+static PHP_METHOD(V8Js, setMemoryLimit)
+{
+	php_v8js_ctx *c;
+	long memory_limit = 0;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &memory_limit) == FAILURE) {
+		return;
+	}
+
+	c = (php_v8js_ctx *) zend_object_store_get_object(getThis() TSRMLS_CC);
+	c->memory_limit = memory_limit;
+}
+/* }}} */
+
 static void php_v8js_persistent_zval_ctor(zval **p) /* {{{ */
 {
 	zval *orig_ptr = *p;
@@ -1738,6 +1782,14 @@ ZEND_END_ARG_INFO()
 ZEND_BEGIN_ARG_INFO(arginfo_v8js_getextensions, 0)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_settimelimit, 0, 0, 1)
+	ZEND_ARG_INFO(0, time_limit)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_setmemorylimit, 0, 0, 1)
+	ZEND_ARG_INFO(0, memory_limit)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO(arginfo_v8jsscriptexception_no_args, 0)
 ZEND_END_ARG_INFO()
 /* }}} */
@@ -1765,6 +1817,8 @@ static const zend_function_entry v8js_methods[] = { /* {{{ */
 	PHP_ME(V8Js,	setModuleLoader,		arginfo_v8js_setmoduleloader,		ZEND_ACC_PUBLIC)
 	PHP_ME(V8Js,	registerExtension,		arginfo_v8js_registerextension,		ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
 	PHP_ME(V8Js,	getExtensions,			arginfo_v8js_getextensions,			ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+	PHP_ME(V8Js,	setTimeLimit,			arginfo_v8js_settimelimit,			ZEND_ACC_PUBLIC)
+	PHP_ME(V8Js,	setMemoryLimit,			arginfo_v8js_setmemorylimit,		ZEND_ACC_PUBLIC)
 #ifdef ENABLE_DEBUGGER_SUPPORT
 	PHP_ME(V8Js,	__destruct,				arginfo_v8js_destruct,				ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
 	PHP_ME(V8Js,	startDebugAgent,		arginfo_v8js_startdebugagent,		ZEND_ACC_PUBLIC)