|
|
@ -41,6 +41,13 @@ impl String { |
|
|
|
/// The amount of arguments this function object takes.
|
|
|
|
/// The amount of arguments this function object takes.
|
|
|
|
pub(crate) const LENGTH: usize = 1; |
|
|
|
pub(crate) const LENGTH: usize = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// JavaScript strings must be between `0` and less than positive `Infinity` and cannot be a negative number.
|
|
|
|
|
|
|
|
/// The range of allowed values can be described like this: `[0, +∞)`.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// The resulting string can also not be larger than the maximum string size,
|
|
|
|
|
|
|
|
/// which can differ in JavaScript engines. In Boa it is `2^32 - 1`
|
|
|
|
|
|
|
|
pub(crate) const MAX_STRING_LENGTH: f64 = u32::MAX as f64; |
|
|
|
|
|
|
|
|
|
|
|
fn this_string_value(this: &Value, ctx: &mut Interpreter) -> Result<RcString, Value> { |
|
|
|
fn this_string_value(this: &Value, ctx: &mut Interpreter) -> Result<RcString, Value> { |
|
|
|
match this { |
|
|
|
match this { |
|
|
|
Value::String(ref string) => return Ok(string.clone()), |
|
|
|
Value::String(ref string) => return Ok(string.clone()), |
|
|
@ -206,16 +213,27 @@ impl String { |
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.repeat
|
|
|
|
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.repeat
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
|
|
|
pub(crate) fn repeat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
pub(crate) fn repeat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
// First we get it the actual string a private field stored on the object only the engine has access to.
|
|
|
|
let object = ctx.require_object_coercible(this)?; |
|
|
|
// Then we convert it into a Rust String by wrapping it in from_value
|
|
|
|
let string = ctx.to_string(object)?; |
|
|
|
let primitive_val = ctx.to_string(this)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let repeat_times = usize::from( |
|
|
|
if let Some(arg) = args.get(0) { |
|
|
|
args.get(0) |
|
|
|
let n = ctx.to_integer(arg)?; |
|
|
|
.expect("failed to get argument for String method"), |
|
|
|
if n < 0.0 { |
|
|
|
); |
|
|
|
return ctx.throw_range_error("repeat count cannot be a negative number"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if n.is_infinite() { |
|
|
|
|
|
|
|
return ctx.throw_range_error("repeat count cannot be infinity"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ok(Value::from(primitive_val.repeat(repeat_times))) |
|
|
|
if n * (string.len() as f64) > Self::MAX_STRING_LENGTH { |
|
|
|
|
|
|
|
return ctx |
|
|
|
|
|
|
|
.throw_range_error("repeat count must not overflow maximum string length"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(string.repeat(n as usize).into()) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
Ok("".into()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// `String.prototype.slice( beginIndex [, endIndex] )`
|
|
|
|
/// `String.prototype.slice( beginIndex [, endIndex] )`
|
|
|
|