Skip to content

Commit 0a12213

Browse files
committed
Exceptions
1 parent 4b62d8a commit 0a12213

File tree

5 files changed

+81
-38
lines changed

5 files changed

+81
-38
lines changed

src/lib.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ use std::collections::HashMap;
1212
mod runtime;
1313

1414
pub use crate::runtime::JSRuntime;
15+
pub use crate::runtime::Error as RuntimeError;
16+
17+
static mut V8JSTIMELIMITEXCEPTION_EXCEPTION: Option<&'static ClassEntry> = None;
18+
static mut V8JSMEMORYLIMITEXCEPTION_EXCEPTION: Option<&'static ClassEntry> = None;
1519

1620
pub fn zval_from_jsvalue(result: v8::Local<v8::Value>, scope: &mut v8::HandleScope) -> Zval {
1721
if result.is_string() {
@@ -207,7 +211,17 @@ impl V8Js {
207211
Ok(zval)
208212
}
209213
},
210-
_ => Err(PhpException::default(String::from("Exception"))),
214+
Err(e) => {
215+
match e {
216+
RuntimeError::ExecutionTimeout => {
217+
Err(PhpException::new("".into(), 0, unsafe{ V8JSTIMELIMITEXCEPTION_EXCEPTION.unwrap() } ))
218+
},
219+
RuntimeError::MemoryLimitExceeded => {
220+
Err(PhpException::new("".into(), 0, unsafe{ V8JSMEMORYLIMITEXCEPTION_EXCEPTION.unwrap() } ))
221+
},
222+
_ => Err(PhpException::default(String::from("Exception")))
223+
}
224+
}
211225
}
212226
}
213227

@@ -447,6 +461,22 @@ pub extern "C" fn php_module_info(_module: *mut ModuleEntry) {
447461
info_table_end!();
448462
}
449463

464+
465+
#[php_startup]
466+
pub fn startup() {
467+
let ce = ClassBuilder::new("V8JsTimeLimitException")
468+
.extends(ce::exception())
469+
.build()
470+
.expect("Failed to build V8JsTimeLimitException");
471+
unsafe { V8JSTIMELIMITEXCEPTION_EXCEPTION.replace(ce) };
472+
473+
let ce = ClassBuilder::new("V8JsMemoryLimitException")
474+
.extends(ce::exception())
475+
.build()
476+
.expect("Failed to build V8JsMemoryLimitException");
477+
unsafe { V8JSMEMORYLIMITEXCEPTION_EXCEPTION.replace(ce) };
478+
}
479+
450480
#[php_module]
451481
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
452482
module.info_function(php_module_info)
@@ -526,6 +556,16 @@ mod integration {
526556
run_php("commonjs_modules.php");
527557
}
528558

559+
#[test]
560+
fn time_limit() {
561+
run_php("time_limit.php");
562+
}
563+
564+
#[test]
565+
fn memory_limit() {
566+
run_php("memory_limit.php");
567+
}
568+
529569
#[test]
530570
fn v8js_version() {
531571
run_php("version.php");

src/runtime.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ impl JSRuntime {
168168
// If we have time / memory limits, we have to spawn a monitoring thread
169169
// to periodically check the run time / memory usage of V8.
170170
if memory_limit.is_some() || time_limit.is_some() {
171-
println!("checking limit");
172171
std::thread::spawn({
173172
let should_i_stop = stop_flag.clone();
174173
let time_limit_hit = time_limit_hit.clone();
@@ -179,7 +178,6 @@ impl JSRuntime {
179178
static MEMORY_LIMIT_HIT_CALLBACK: std::sync::atomic::AtomicBool =
180179
std::sync::atomic::AtomicBool::new(false);
181180
move || {
182-
println!("{:#?}", time_limit);
183181
// Callbacl function that is passed to V8. This is not able to catpure
184182
// anythign locally, so we use a static to flag whether the memory limit is
185183
// hit. The c_void pointer called in to the callback is used to pass the
@@ -194,9 +192,7 @@ impl JSRuntime {
194192
}
195193
}
196194
while !should_i_stop.load(std::sync::atomic::Ordering::SeqCst) {
197-
println!("{:#?}", time_limit);
198195
if time_limit.as_millis() > 0 {
199-
println!("checlig limimt");
200196
if start.elapsed() > time_limit
201197
&& !isolate_handle.is_execution_terminating()
202198
{

tests/memory_limit.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
$v8js = new V8Js;
4+
$v8js->sleep = function ( int $milliseconds ) {
5+
usleep( $milliseconds * 1000 );
6+
};
7+
8+
$killed = null;
9+
$used_memory_limit_exception = false;
10+
try {
11+
$result = $v8js->executeString( 'let my_arr = []; for ( let i = 0; i < 100000 ; i++ ) { my_arr.push( (new Date).toString() ); }; ', null, null, null, 1024 * 10 );
12+
$killed = false;
13+
} catch ( V8JsMemoryLimitException $e ) {
14+
$killed = true;
15+
$used_memory_limit_exception = true;
16+
} catch ( Exception $e ) {
17+
$killed = true;
18+
}
19+
assert( $killed === true );
20+
assert( $used_memory_limit_exception === true );

tests/resource_limits.php

Lines changed: 0 additions & 33 deletions
This file was deleted.

tests/time_limit.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
$v8js = new V8Js;
4+
$v8js->sleep = function ( int $milliseconds ) {
5+
usleep( $milliseconds * 1000 );
6+
};
7+
8+
$killed = null;
9+
$used_time_limit_exception = false;
10+
try {
11+
$result = $v8js->executeString( 'for ( let i = 0; i < 100 ; i++ ) { PHP.sleep(100); }; "done"', null, null, 100 );
12+
$killed = false;
13+
} catch( V8JsTimeLimitException ) {
14+
$killed = true;
15+
$used_time_limit_exception = true;
16+
} catch ( Exception $e ) {
17+
$killed = true;
18+
}
19+
assert( $killed === true );
20+
assert( $used_time_limit_exception === true );

0 commit comments

Comments
 (0)