From cec98927f32684497f6b73c5a5a6b192d999a540 Mon Sep 17 00:00:00 2001 From: Haled Odat <8566042+HalidOdat@users.noreply.github.com> Date: Sun, 22 Oct 2023 14:45:22 +0200 Subject: [PATCH] Implement `get/set $boa.limits.stack` (#3385) --- boa_cli/src/debug/limits.rs | 33 +++++++++++++++++++++++++++++ boa_engine/src/vm/runtime_limits.rs | 2 +- docs/boa_object.md | 14 ++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/boa_cli/src/debug/limits.rs b/boa_cli/src/debug/limits.rs index bfbdda4e613..b0dfe8beaaa 100644 --- a/boa_cli/src/debug/limits.rs +++ b/boa_cli/src/debug/limits.rs @@ -16,6 +16,22 @@ fn set_loop(_: &JsValue, args: &[JsValue], context: &mut Context<'_>) -> JsResul Ok(JsValue::undefined()) } +fn get_stack(_: &JsValue, _: &[JsValue], context: &mut Context<'_>) -> JsResult { + let max = context.runtime_limits().stack_size_limit(); + Ok(JsValue::from(max)) +} + +fn set_stack(_: &JsValue, args: &[JsValue], context: &mut Context<'_>) -> JsResult { + let value = args.get_or_undefined(0).to_length(context)?; + let Ok(value) = value.try_into() else { + return Err(JsNativeError::range() + .with_message(format!("Argument {value} greater than usize::MAX")) + .into()); + }; + context.runtime_limits_mut().set_stack_size_limit(value); + Ok(JsValue::undefined()) +} + fn get_recursion(_: &JsValue, _: &[JsValue], context: &mut Context<'_>) -> JsResult { let max = context.runtime_limits().recursion_limit(); Ok(JsValue::from(max)) @@ -44,6 +60,17 @@ pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { .length(1) .build(); + let get_stack = + FunctionObjectBuilder::new(context.realm(), NativeFunction::from_fn_ptr(get_stack)) + .name("get stack") + .length(0) + .build(); + let set_stack = + FunctionObjectBuilder::new(context.realm(), NativeFunction::from_fn_ptr(set_stack)) + .name("set stack") + .length(1) + .build(); + let get_recursion = FunctionObjectBuilder::new(context.realm(), NativeFunction::from_fn_ptr(get_recursion)) .name("get recursion") @@ -61,6 +88,12 @@ pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { Some(set_loop), Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) + .accessor( + js_string!("stack"), + Some(get_stack), + Some(set_stack), + Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, + ) .accessor( js_string!("recursion"), Some(get_recursion), diff --git a/boa_engine/src/vm/runtime_limits.rs b/boa_engine/src/vm/runtime_limits.rs index 5d41451e302..bc78205ffa1 100644 --- a/boa_engine/src/vm/runtime_limits.rs +++ b/boa_engine/src/vm/runtime_limits.rs @@ -16,7 +16,7 @@ impl Default for RuntimeLimits { fn default() -> Self { Self { loop_iteration_limit: u64::MAX, - resursion_limit: 400, + resursion_limit: 512, stack_size_limit: 1024, } } diff --git a/docs/boa_object.md b/docs/boa_object.md index 3477d83c2fc..64bc38a6872 100644 --- a/docs/boa_object.md +++ b/docs/boa_object.md @@ -259,6 +259,20 @@ $boa.limits.loop = 10; while (true) {} // RuntimeLimit: Maximum loop iteration limit 10 exceeded ``` +### Getter & Setter `$boa.limits.stack` + +This is an accessor property on the module, its getter returns the value stack limit before an error is thrown. +Its setter can be used to set the recursion limit. + +```javascript +$boa.limits.stack = 10; + +function x() { + return; +} +x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // RuntimeLimit: exceeded maximum call stack length +``` + ### Getter & Setter `$boa.limits.recursion` This is an accessor property on the module, its getter returns the recursion limit before an error is thrown.