Browse Source

Added documentation to RegExp

pull/293/head
HalidOdat 5 years ago
parent
commit
b525f68ff6
  1. 46
      boa/src/builtins/array/mod.rs
  2. 8
      boa/src/builtins/json.rs
  3. 8
      boa/src/builtins/number/mod.rs
  4. 170
      boa/src/builtins/regexp/mod.rs
  5. 60
      boa/src/builtins/string/mod.rs

46
boa/src/builtins/array/mod.rs

@ -48,8 +48,10 @@ pub(crate) fn new_array(interpreter: &Interpreter) -> ResultValue {
Ok(array) Ok(array)
} }
/// Utility function for creating array objects: `array_obj` can be any array with /// Utility function for creating array objects.
/// prototype already set (it will be wiped and recreated from `array_contents`) ///
/// `array_obj` can be any array with prototype already set (it will be wiped and
/// recreated from `array_contents`)
pub fn construct_array(array_obj: &Value, array_contents: &[Value]) -> ResultValue { pub fn construct_array(array_obj: &Value, array_contents: &[Value]) -> ResultValue {
let array_obj_ptr = array_obj.clone(); let array_obj_ptr = array_obj.clone();
@ -128,7 +130,7 @@ pub fn make_array(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result
Ok(this.clone()) Ok(this.clone())
} }
/// Array.isArray ( arg ) /// `Array.isArray( arg )`
/// ///
/// The isArray function takes one argument arg, and returns the Boolean value true /// The isArray function takes one argument arg, and returns the Boolean value true
/// if the argument is an object whose class internal property is "Array"; otherwise it returns false. /// if the argument is an object whose class internal property is "Array"; otherwise it returns false.
@ -162,7 +164,7 @@ pub fn is_array(_this: &Value, args: &[Value], _interpreter: &mut Interpreter) -
} }
} }
/// Array.prototype.concat(...arguments) /// `Array.prototype.concat(...arguments)`
/// ///
/// When the concat method is called with zero or more arguments, it returns an /// When the concat method is called with zero or more arguments, it returns an
/// array containing the array elements of the object followed by the array /// array containing the array elements of the object followed by the array
@ -201,7 +203,7 @@ pub fn concat(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue
construct_array(this, &new_values) construct_array(this, &new_values)
} }
/// Array.prototype.push ( ...items ) /// `Array.prototype.push( ...items )`
/// ///
/// The arguments are appended to the end of the array, in the order in which /// The arguments are appended to the end of the array, in the order in which
/// they appear. The new length of the array is returned as the result of the /// they appear. The new length of the array is returned as the result of the
@ -218,7 +220,7 @@ pub fn push(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(new_array.get_field_slice("length")) Ok(new_array.get_field_slice("length"))
} }
/// Array.prototype.pop ( ) /// `Array.prototype.pop()`
/// ///
/// The last element of the array is removed from the array and returned. /// The last element of the array is removed from the array and returned.
/// ///
@ -241,7 +243,7 @@ pub fn pop(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(pop_value) Ok(pop_value)
} }
/// Array.prototype.forEach ( callbackFn [ , thisArg ] ) /// `Array.prototype.forEach( callbackFn [ , thisArg ] )`
/// ///
/// This method executes the provided callback function for each element in the array. /// This method executes the provided callback function for each element in the array.
/// ///
@ -274,7 +276,7 @@ pub fn for_each(this: &Value, args: &[Value], interpreter: &mut Interpreter) ->
Ok(Gc::new(ValueData::Undefined)) Ok(Gc::new(ValueData::Undefined))
} }
/// Array.prototype.join ( separator ) /// `Array.prototype.join( separator )`
/// ///
/// The elements of the array are converted to Strings, and these Strings are /// The elements of the array are converted to Strings, and these Strings are
/// then concatenated, separated by occurrences of the separator. If no /// then concatenated, separated by occurrences of the separator. If no
@ -304,7 +306,7 @@ pub fn join(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(to_value(elem_strs.join(&separator))) Ok(to_value(elem_strs.join(&separator)))
} }
/// Array.prototype.toString ( separator ) /// `Array.prototype.toString( separator )`
/// ///
/// The toString function is intentionally generic; it does not require that /// The toString function is intentionally generic; it does not require that
/// its this value be an Array object. Therefore it can be transferred to /// its this value be an Array object. Therefore it can be transferred to
@ -346,7 +348,7 @@ pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> Resul
Ok(to_value(match_string)) Ok(to_value(match_string))
} }
/// Array.prototype.reverse ( ) /// `Array.prototype.reverse()`
/// ///
/// The elements of the array are rearranged so as to reverse their order. /// The elements of the array are rearranged so as to reverse their order.
/// The object is returned as the result of the call. /// The object is returned as the result of the call.
@ -387,7 +389,7 @@ pub fn reverse(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(this.clone()) Ok(this.clone())
} }
/// Array.prototype.shift ( ) /// `Array.prototype.shift()`
/// ///
/// The first element of the array is removed from the array and returned. /// The first element of the array is removed from the array and returned.
/// ///
@ -428,7 +430,7 @@ pub fn shift(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(first) Ok(first)
} }
/// Array.prototype.unshift ( ...items ) /// `Array.prototype.unshift( ...items )`
/// ///
/// The arguments are prepended to the start of the array, such that their order /// The arguments are prepended to the start of the array, such that their order
/// within the array is the same as the order in which they appear in the /// within the array is the same as the order in which they appear in the
@ -472,7 +474,7 @@ pub fn unshift(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue
Ok(to_value(temp)) Ok(to_value(temp))
} }
/// Array.prototype.every ( callback, [ thisArg ] ) /// `Array.prototype.every( callback, [ thisArg ] )`
/// ///
/// The every method executes the provided callback function once for each /// The every method executes the provided callback function once for each
/// element present in the array until it finds the one where callback returns /// element present in the array until it finds the one where callback returns
@ -513,7 +515,7 @@ pub fn every(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Res
Ok(to_value(true)) Ok(to_value(true))
} }
/// Array.prototype.map ( callback, [ thisArg ] ) /// `Array.prototype.map( callback, [ thisArg ] )`
/// ///
/// For each element in the array the callback function is called, and a new /// For each element in the array the callback function is called, and a new
/// array is constructed from the return values of these calls. /// array is constructed from the return values of these calls.
@ -554,7 +556,7 @@ pub fn map(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resul
construct_array(&new, &values) construct_array(&new, &values)
} }
/// Array.prototype.indexOf ( searchElement[, fromIndex ] ) /// `Array.prototype.indexOf( searchElement[, fromIndex ] )`
/// ///
/// ///
/// indexOf compares searchElement to the elements of the array, in ascending order, /// indexOf compares searchElement to the elements of the array, in ascending order,
@ -610,7 +612,7 @@ pub fn index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValu
Ok(to_value(-1)) Ok(to_value(-1))
} }
/// Array.prototype.lastIndexOf ( searchElement[, fromIndex ] ) /// `Array.prototype.lastIndexOf( searchElement[, fromIndex ] )`
/// ///
/// ///
/// lastIndexOf compares searchElement to the elements of the array in descending order /// lastIndexOf compares searchElement to the elements of the array in descending order
@ -665,7 +667,7 @@ pub fn last_index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> Resul
Ok(to_value(-1)) Ok(to_value(-1))
} }
/// Array.prototype.find ( callback, [thisArg] ) /// `Array.prototype.find( callback, [thisArg] )`
/// ///
/// The find method executes the callback function once for each index of the array /// The find method executes the callback function once for each index of the array
/// until the callback returns a truthy value. If so, find immediately returns the value /// until the callback returns a truthy value. If so, find immediately returns the value
@ -701,7 +703,7 @@ pub fn find(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resu
Ok(Gc::new(ValueData::Undefined)) Ok(Gc::new(ValueData::Undefined))
} }
/// Array.prototype.findIndex ( predicate [ , thisArg ] ) /// `Array.prototype.findIndex( predicate [ , thisArg ] )`
/// ///
/// This method executes the provided predicate function for each element of the array. /// This method executes the provided predicate function for each element of the array.
/// If the predicate function returns `true` for an element, this method returns the index of the element. /// If the predicate function returns `true` for an element, this method returns the index of the element.
@ -744,7 +746,7 @@ pub fn find_index(this: &Value, args: &[Value], interpreter: &mut Interpreter) -
Ok(Gc::new(ValueData::Number(f64::from(-1)))) Ok(Gc::new(ValueData::Number(f64::from(-1))))
} }
/// Array.prototype.fill ( value[, start[, end]] ) /// `Array.prototype.fill( value[, start[, end]] )`
/// ///
/// The method fills (modifies) all the elements of an array from start index (default 0) /// The method fills (modifies) all the elements of an array from start index (default 0)
/// to an end index (default array length) with a static value. It returns the modified array. /// to an end index (default array length) with a static value. It returns the modified array.
@ -784,7 +786,7 @@ pub fn fill(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(this.clone()) Ok(this.clone())
} }
/// Array.prototype.includes( valueToFind [, fromIndex] ) /// `Array.prototype.includes( valueToFind [, fromIndex] )`
/// ///
/// Determines whether an array includes a certain value among its entries, returning `true` or `false` as appropriate. /// Determines whether an array includes a certain value among its entries, returning `true` or `false` as appropriate.
/// ///
@ -814,7 +816,7 @@ pub fn includes_value(this: &Value, args: &[Value], _: &mut Interpreter) -> Resu
Ok(to_value(false)) Ok(to_value(false))
} }
/// Array.prototype.slice ( [begin[, end]] ) /// `Array.prototype.slice( [begin[, end]] )`
/// ///
/// The slice method takes two arguments, start and end, and returns an array containing the /// The slice method takes two arguments, start and end, and returns an array containing the
/// elements of the array from element start up to, but not including, element end (or through the /// elements of the array from element start up to, but not including, element end (or through the
@ -866,7 +868,7 @@ pub fn slice(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> Res
Ok(new_array) Ok(new_array)
} }
/// Array.prototype.filter ( callback, [ thisArg ] ) /// `Array.prototype.filter( callback, [ thisArg ] )`
/// ///
/// For each element in the array the callback function is called, and a new /// For each element in the array the callback function is called, and a new
/// array is constructed for every value whose callback returned a truthy value. /// array is constructed for every value whose callback returned a truthy value.

8
boa/src/builtins/json.rs

@ -19,7 +19,9 @@ use crate::builtins::value::{to_value, ResultValue, Value, ValueData};
use crate::exec::Interpreter; use crate::exec::Interpreter;
use serde_json::{self, Value as JSONValue}; use serde_json::{self, Value as JSONValue};
/// The `JSON` method parses a JSON string, constructing the JavaScript value or object described by the string. /// `JSON.parse( text[, reviver] )`
///
/// This `JSON` method parses a JSON string, constructing the JavaScript value or object described by the string.
/// ///
/// An optional `reviver` function can be provided to perform a transformation on the resulting object before it is returned. /// An optional `reviver` function can be provided to perform a transformation on the resulting object before it is returned.
/// ///
@ -43,7 +45,9 @@ pub fn parse(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
} }
} }
/// The `JSON` method converts a JavaScript object or value to a JSON string. /// `JSON.stringify( value[, replacer[, space]] )`
///
/// This `JSON` method converts a JavaScript object or value to a JSON string.
/// ///
/// This medhod optionally replaces values if a `replacer` function is specified or /// This medhod optionally replaces values if a `replacer` function is specified or
/// optionally including only the specified properties if a replacer array is specified. /// optionally including only the specified properties if a replacer array is specified.

8
boa/src/builtins/number/mod.rs

@ -117,7 +117,7 @@ pub fn to_fixed(this: &Value, args: &[Value], _ctx: &mut Interpreter) -> ResultV
/// ///
/// Note that while this technically conforms to the Ecma standard, it does no actual /// Note that while this technically conforms to the Ecma standard, it does no actual
/// internationalization logic. /// internationalization logic.
/// ///
/// More information: /// More information:
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn] /// - [MDN documentation][mdn]
@ -131,7 +131,7 @@ pub fn to_locale_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -
} }
/// The `toPrecision()` method returns a string representing the Number object to the specified precision. /// The `toPrecision()` method returns a string representing the Number object to the specified precision.
/// ///
/// More information: /// More information:
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn] /// - [MDN documentation][mdn]
@ -153,7 +153,7 @@ pub fn to_precision(this: &Value, args: &[Value], _ctx: &mut Interpreter) -> Res
} }
/// The `toString()` method returns a string representing the specified Number object. /// The `toString()` method returns a string representing the specified Number object.
/// ///
/// More information: /// More information:
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn] /// - [MDN documentation][mdn]
@ -165,7 +165,7 @@ pub fn to_string(this: &Value, _args: &[Value], _ctx: &mut Interpreter) -> Resul
} }
/// The `valueOf()` method returns the wrapped primitive value of a Number object. /// The `valueOf()` method returns the wrapped primitive value of a Number object.
/// ///
/// More information: /// More information:
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn] /// - [MDN documentation][mdn]

170
boa/src/builtins/regexp/mod.rs

@ -1,3 +1,14 @@
//! This module implements the global `RegExp` object.
//!
//! `The `RegExp` object is used for matching text with a pattern.
//!
//! More information:
//! - [ECMAScript reference][spec]
//! - [MDN documentation][mdn]
//!
//! [spec]: https://tc39.es/ecma262/#sec-regexp-constructor
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
use std::ops::Deref; use std::ops::Deref;
use gc::Gc; use gc::Gc;
@ -13,30 +24,40 @@ use crate::{
exec::Interpreter, exec::Interpreter,
}; };
/// The internal representation on a `RegExp` object.
#[derive(Debug)] #[derive(Debug)]
struct RegExp { struct RegExp {
/// Regex matcher. /// Regex matcher.
matcher: Regex, matcher: Regex,
/// Update last_index, set if global or sticky flags are set. /// Update last_index, set if global or sticky flags are set.
use_last_index: bool, use_last_index: bool,
/// String of parsed flags. /// String of parsed flags.
flags: String, flags: String,
/// Flag 's' - dot matches newline characters. /// Flag 's' - dot matches newline characters.
dot_all: bool, dot_all: bool,
/// Flag 'g' /// Flag 'g'
global: bool, global: bool,
/// Flag 'i' - ignore case. /// Flag 'i' - ignore case.
ignore_case: bool, ignore_case: bool,
/// Flag 'm' - '^' and '$' match beginning/end of line. /// Flag 'm' - '^' and '$' match beginning/end of line.
multiline: bool, multiline: bool,
/// Flag 'y' /// Flag 'y'
sticky: bool, sticky: bool,
/// Flag 'u' - Unicode. /// Flag 'u' - Unicode.
unicode: bool, unicode: bool,
} }
impl InternalState for RegExp {} impl InternalState for RegExp {}
/// Helper function for getting an argument.
fn get_argument<T: FromValue>(args: &[Value], idx: usize) -> Result<T, Value> { fn get_argument<T: FromValue>(args: &[Value], idx: usize) -> Result<T, Value> {
match args.get(idx) { match args.get(idx) {
Some(arg) => from_value(arg.clone()).map_err(to_value), Some(arg) => from_value(arg.clone()).map_err(to_value),
@ -150,43 +171,138 @@ pub fn make_regexp(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultV
Ok(this.clone()) Ok(this.clone())
} }
/// `RegExp.prototype.dotAll`
///
/// The `dotAll` property indicates whether or not the "`s`" flag is used with the regular expression.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.dotAll
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/dotAll
fn get_dot_all(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_dot_all(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.dot_all))) this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.dot_all)))
} }
/// `RegExp.prototype.flags`
///
/// The `flags` property returns a string consisting of the [`flags`][flags] of the current regular expression object.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags
/// [flags]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Advanced_searching_with_flags_2
fn get_flags(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_flags(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.flags.clone()))) this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.flags.clone())))
} }
/// `RegExp.prototype.global`
///
/// The `global` property indicates whether or not the "`g`" flag is used with the regular expression.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.global
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global
fn get_global(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_global(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.global))) this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.global)))
} }
/// `RegExp.prototype.ignoreCase`
///
/// The `ignoreCase` property indicates whether or not the "`i`" flag is used with the regular expression.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.ignorecase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase
fn get_ignore_case(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_ignore_case(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.ignore_case))) this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.ignore_case)))
} }
/// `RegExp.prototype.multiline`
///
/// The multiline property indicates whether or not the "m" flag is used with the regular expression.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.multiline
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/multiline
fn get_multiline(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_multiline(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.multiline))) this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.multiline)))
} }
/// `RegExp.prototype.source`
///
/// The `source` property returns a `String` containing the source text of the regexp object,
/// and it doesn't contain the two forward slashes on both sides and any flags.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.source
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source
fn get_source(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_source(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
Ok(this.get_internal_slot("OriginalSource")) Ok(this.get_internal_slot("OriginalSource"))
} }
/// `RegExp.prototype.sticky`
///
/// The `flags` property returns a string consisting of the [`flags`][flags] of the current regular expression object.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.sticky
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky
fn get_sticky(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_sticky(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.sticky))) this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.sticky)))
} }
/// `RegExp.prototype.unicode`
///
/// The unicode property indicates whether or not the "`u`" flag is used with a regular expression.
/// unicode is a read-only property of an individual regular expression instance.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.unicode
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode
fn get_unicode(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { fn get_unicode(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.unicode))) this.with_internal_state_ref(|regex: &RegExp| Ok(to_value(regex.unicode)))
} }
/// Helper function.
fn _make_prop(getter: NativeFunctionData) -> Property { fn _make_prop(getter: NativeFunctionData) -> Property {
Property::default().get(to_value(getter)) Property::default().get(to_value(getter))
} }
/// Search for a match between this regex and a specified string /// `RegExp.prototype.test( string )`
///
/// The `test()` method executes a search for a match between a regular expression and a specified string.
///
/// Returns `true` or `false`.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.test
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
pub fn test(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { pub fn test(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let arg_str = get_argument::<String>(args, 0)?; let arg_str = get_argument::<String>(args, 0)?;
let mut last_index = let mut last_index =
@ -209,7 +325,18 @@ pub fn test(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
result result
} }
/// Search for a match between this regex and a specified string /// `RegExp.prototype.exec( string )`
///
/// The exec() method executes a search for a match in a specified string.
///
/// Returns a result array, or `null`.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
pub fn exec(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { pub fn exec(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let arg_str = get_argument::<String>(args, 0)?; let arg_str = get_argument::<String>(args, 0)?;
let mut last_index = let mut last_index =
@ -250,8 +377,16 @@ pub fn exec(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
result result
} }
/// RegExp.prototype[Symbol.match] /// `RegExp.prototype[ @@match ]( string )`
/// Returns matches of the regular expression against a string ///
/// This method retrieves the matches when matching a string against a regular expression.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@match
pub fn r#match(this: &Value, arg: String, ctx: &mut Interpreter) -> ResultValue { pub fn r#match(this: &Value, arg: String, ctx: &mut Interpreter) -> ResultValue {
let (matcher, flags) = let (matcher, flags) =
this.with_internal_state_ref(|regex: &RegExp| (regex.matcher.clone(), regex.flags.clone())); this.with_internal_state_ref(|regex: &RegExp| (regex.matcher.clone(), regex.flags.clone()));
@ -269,16 +404,33 @@ pub fn r#match(this: &Value, arg: String, ctx: &mut Interpreter) -> ResultValue
} }
} }
/// Return a string representing the regular expression /// `RegExp.prototype.toString()`
///
/// Return a string representing the regular expression.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString
pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
let body = from_value::<String>(this.get_internal_slot("OriginalSource")).map_err(to_value)?; let body = from_value::<String>(this.get_internal_slot("OriginalSource")).map_err(to_value)?;
let flags = this.with_internal_state_ref(|regex: &RegExp| regex.flags.clone()); let flags = this.with_internal_state_ref(|regex: &RegExp| regex.flags.clone());
Ok(to_value(format!("/{}/{}", body, flags))) Ok(to_value(format!("/{}/{}", body, flags)))
} }
/// RegExp.prototype[Symbol.matchAll] /// `RegExp.prototype[ @@matchAll ]( string )`
/// Returns all matches of the regular expression against a string ///
/// TODO: it's returning an array, it should return an iterator /// The `[@@matchAll]` method returns all matches of the regular expression against a string.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp-prototype-matchall
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@matchAll
// TODO: it's returning an array, it should return an iterator
pub fn match_all(this: &Value, arg_str: String) -> ResultValue { pub fn match_all(this: &Value, arg_str: String) -> ResultValue {
let matches: Vec<Value> = this.with_internal_state_ref(|regex: &RegExp| { let matches: Vec<Value> = this.with_internal_state_ref(|regex: &RegExp| {
let mut matches = Vec::new(); let mut matches = Vec::new();
@ -319,7 +471,7 @@ pub fn match_all(this: &Value, arg_str: String) -> ResultValue {
Ok(result) Ok(result)
} }
/// Create a new `RegExp` object /// Create a new `RegExp` object.
pub fn create_constructor(global: &Value) -> Value { pub fn create_constructor(global: &Value) -> Value {
// Create constructor function // Create constructor function
let mut regexp_constructor = Object::default(); let mut regexp_constructor = Object::default();

60
boa/src/builtins/string/mod.rs

@ -73,6 +73,8 @@ pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue
Ok(to_value(format!("{}", primitive_val))) Ok(to_value(format!("{}", primitive_val)))
} }
/// `String.prototype.charAt( index )`
///
/// The `String` object's `charAt()` method returns a new string consisting of the single UTF-16 code unit located at the specified offset into the string. /// The `String` object's `charAt()` method returns a new string consisting of the single UTF-16 code unit located at the specified offset into the string.
/// ///
/// Characters in a string are indexed from left to right. The index of the first character is `0`, /// Characters in a string are indexed from left to right. The index of the first character is `0`,
@ -80,7 +82,7 @@ pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue
/// If the `index` you supply is out of this range, JavaScript returns an empty string. /// If the `index` you supply is out of this range, JavaScript returns an empty string.
/// ///
/// If no index is provided to `charAt()`, the default is `0`. /// If no index is provided to `charAt()`, the default is `0`.
/// ///
/// More information: /// More information:
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn] /// - [MDN documentation][mdn]
@ -117,6 +119,8 @@ pub fn char_at(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultVal
)) ))
} }
/// `String.prototype.charCodeAt( index )`
///
/// The `charCodeAt()` method returns an integer between `0` and `65535` representing the UTF-16 code unit at the given index. /// The `charCodeAt()` method returns an integer between `0` and `65535` representing the UTF-16 code unit at the given index.
/// ///
/// Unicode code points range from `0` to `1114111` (`0x10FFFF`). The first 128 Unicode code points are a direct match of the ASCII character encoding. /// Unicode code points range from `0` to `1114111` (`0x10FFFF`). The first 128 Unicode code points are a direct match of the ASCII character encoding.
@ -157,12 +161,14 @@ pub fn char_code_at(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Resu
Ok(to_value(f64::from(utf16_val))) Ok(to_value(f64::from(utf16_val)))
} }
/// `String.prototype.concat( str1[, ...strN] )`
///
/// The `concat()` method concatenates the string arguments to the calling string and returns a new string. /// The `concat()` method concatenates the string arguments to the calling string and returns a new string.
/// ///
/// Changes to the original string or the returned string don't affect the other. /// Changes to the original string or the returned string don't affect the other.
/// ///
/// If the arguments are not of the type string, they are converted to string values before concatenating. /// If the arguments are not of the type string, they are converted to string values before concatenating.
/// ///
/// More information: /// More information:
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn] /// - [MDN documentation][mdn]
@ -182,6 +188,8 @@ pub fn concat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValu
Ok(to_value(new_str)) Ok(to_value(new_str))
} }
/// `String.prototype.repeat( count )`
///
/// The `repeat()` method constructs and returns a new string which contains the specified number of /// The `repeat()` method constructs and returns a new string which contains the specified number of
/// copies of the string on which it was called, concatenated together. /// copies of the string on which it was called, concatenated together.
/// ///
@ -205,6 +213,8 @@ pub fn repeat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValu
Ok(to_value(primitive_val.repeat(repeat_times))) Ok(to_value(primitive_val.repeat(repeat_times)))
} }
/// `String.prototype.slice( beginIndex [, endIndex] )`
///
/// The `slice()` method extracts a section of a string and returns it as a new string, without modifying the original string. /// The `slice()` method extracts a section of a string and returns it as a new string, without modifying the original string.
/// ///
/// More information: /// More information:
@ -260,6 +270,8 @@ pub fn slice(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue
Ok(to_value(new_str)) Ok(to_value(new_str))
} }
/// `String.prototype.startWith( searchString[, position] )`
///
/// The `startsWith()` method determines whether a string begins with the characters of a specified string, returning `true` or `false` as appropriate. /// The `startsWith()` method determines whether a string begins with the characters of a specified string, returning `true` or `false` as appropriate.
/// ///
/// More information: /// More information:
@ -303,6 +315,8 @@ pub fn starts_with(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Resul
} }
} }
/// `String.prototype.endsWith( searchString[, length] )`
///
/// The `endsWith()` method determines whether a string ends with the characters of a specified string, returning `true` or `false` as appropriate. /// The `endsWith()` method determines whether a string ends with the characters of a specified string, returning `true` or `false` as appropriate.
/// ///
/// More information: /// More information:
@ -348,6 +362,8 @@ pub fn ends_with(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultV
} }
} }
/// `String.prototype.includes( searchString[, position] )`
///
/// The `includes()` method determines whether one string may be found within another string, returning `true` or `false` as appropriate. /// The `includes()` method determines whether one string may be found within another string, returning `true` or `false` as appropriate.
/// ///
/// More information: /// More information:
@ -406,11 +422,13 @@ fn get_regex_string(value: &Value) -> String {
} }
} }
/// `String.prototype.replace( regexp|substr, newSubstr|function )`
///
/// The `replace()` method returns a new string with some or all matches of a `pattern` replaced by a `replacement`. /// The `replace()` method returns a new string with some or all matches of a `pattern` replaced by a `replacement`.
/// ///
/// The `pattern` can be a string or a `RegExp`, and the `replacement` can be a string or a function to be called for each match. /// The `pattern` can be a string or a `RegExp`, and the `replacement` can be a string or a function to be called for each match.
/// If `pattern` is a string, only the first occurrence will be replaced. /// If `pattern` is a string, only the first occurrence will be replaced.
/// ///
/// The original string is left unchanged. /// The original string is left unchanged.
/// ///
/// More information: /// More information:
@ -509,6 +527,8 @@ pub fn replace(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultVal
))) )))
} }
/// `String.prototype.indexOf( searchValue[, fromIndex] )`
///
/// The `indexOf()` method returns the index within the calling `String` object of the first occurrence of the specified value, starting the search at `fromIndex`. /// The `indexOf()` method returns the index within the calling `String` object of the first occurrence of the specified value, starting the search at `fromIndex`.
/// ///
/// Returns -1 if the value is not found. /// Returns -1 if the value is not found.
@ -559,7 +579,9 @@ pub fn index_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultVa
Ok(to_value(-1)) Ok(to_value(-1))
} }
//// The `lastIndexOf()` method returns the index within the calling `String` object of the last occurrence of the specified value, searching backwards from `fromIndex`. /// `String.prototype.lastIndexOf( searchValue[, fromIndex] )`
///
/// The `lastIndexOf()` method returns the index within the calling `String` object of the last occurrence of the specified value, searching backwards from `fromIndex`.
/// ///
/// Returns -1 if the value is not found. /// Returns -1 if the value is not found.
/// ///
@ -610,6 +632,8 @@ pub fn last_index_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Res
Ok(to_value(highest_index)) Ok(to_value(highest_index))
} }
/// `String.prototype.match( regexp )`
///
/// The `match()` method retrieves the result of matching a **string** against a [`regular expression`][regex]. /// The `match()` method retrieves the result of matching a **string** against a [`regular expression`][regex].
/// ///
/// More information: /// More information:
@ -624,7 +648,8 @@ pub fn r#match(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultVal
regexp_match(&re, ctx.value_to_rust_string(this), ctx) regexp_match(&re, ctx.value_to_rust_string(this), ctx)
} }
/// Abstract method `StringPad` /// Abstract method `StringPad`.
///
/// Performs the actual string padding for padStart/End. /// Performs the actual string padding for padStart/End.
/// <https://tc39.es/ecma262/#sec-stringpad/> /// <https://tc39.es/ecma262/#sec-stringpad/>
fn string_pad( fn string_pad(
@ -664,6 +689,8 @@ fn string_pad(
} }
} }
/// `String.prototype.padEnd( targetLength[, padString] )`
///
/// The `padEnd()` method pads the current string with a given string (repeated, if needed) so that the resulting string reaches a given length. /// The `padEnd()` method pads the current string with a given string (repeated, if needed) so that the resulting string reaches a given length.
/// ///
/// The padding is applied from the end of the current string. /// The padding is applied from the end of the current string.
@ -696,6 +723,8 @@ pub fn pad_end(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultVal
string_pad(primitive_val, max_length, fill_string, false) string_pad(primitive_val, max_length, fill_string, false)
} }
/// `String.prototype.padStart( targetLength [, padString] )`
///
/// The `padStart()` method pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. /// The `padStart()` method pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length.
/// ///
/// The padding is applied from the start of the current string. /// The padding is applied from the start of the current string.
@ -728,6 +757,7 @@ pub fn pad_start(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultV
string_pad(primitive_val, max_length, fill_string, true) string_pad(primitive_val, max_length, fill_string, true)
} }
/// Helper function to check if a `char` is trimmable.
fn is_trimmable_whitespace(c: char) -> bool { fn is_trimmable_whitespace(c: char) -> bool {
// The rust implementation of `trim` does not regard the same characters whitespace as ecma standard does // The rust implementation of `trim` does not regard the same characters whitespace as ecma standard does
// //
@ -746,6 +776,8 @@ fn is_trimmable_whitespace(c: char) -> bool {
} }
} }
/// String.prototype.trim()
///
/// The `trim()` method removes whitespace from both ends of a string. /// The `trim()` method removes whitespace from both ends of a string.
/// ///
/// Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.). /// Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.).
@ -761,6 +793,8 @@ pub fn trim(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
Ok(to_value(this_str.trim_matches(is_trimmable_whitespace))) Ok(to_value(this_str.trim_matches(is_trimmable_whitespace)))
} }
/// `String.prototype.trimStart()`
///
/// The `trimStart()` method removes whitespace from the beginning of a string. /// The `trimStart()` method removes whitespace from the beginning of a string.
/// ///
/// Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.). /// Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.).
@ -778,6 +812,8 @@ pub fn trim_start(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultVal
)) ))
} }
/// String.prototype.trimEnd()
///
/// The `trimEnd()` method removes whitespace from the end of a string. /// The `trimEnd()` method removes whitespace from the end of a string.
/// ///
/// Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.). /// Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.).
@ -793,6 +829,8 @@ pub fn trim_end(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue
Ok(to_value(this_str.trim_end_matches(is_trimmable_whitespace))) Ok(to_value(this_str.trim_end_matches(is_trimmable_whitespace)))
} }
/// `String.prototype.toLowerCase()`
///
/// The `toLowerCase()` method returns the calling string value converted to lower case. /// The `toLowerCase()` method returns the calling string value converted to lower case.
/// ///
/// More information: /// More information:
@ -810,6 +848,8 @@ pub fn to_lowercase(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultV
Ok(to_value(this_str.to_lowercase())) Ok(to_value(this_str.to_lowercase()))
} }
/// `String.prototype.toUpperCase()`
///
/// The `toUpperCase()` method returns the calling string value converted to uppercase. /// The `toUpperCase()` method returns the calling string value converted to uppercase.
/// ///
/// The value will be **converted** to a string if it isn't one /// The value will be **converted** to a string if it isn't one
@ -829,6 +869,8 @@ pub fn to_uppercase(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultV
Ok(to_value(this_str.to_uppercase())) Ok(to_value(this_str.to_uppercase()))
} }
/// `String.prototype.substring( indexStart[, indexEnd] )`
///
/// The `substring()` method returns the part of the `string` between the start and end indexes, or to the end of the string. /// The `substring()` method returns the part of the `string` between the start and end indexes, or to the end of the string.
/// ///
/// More information: /// More information:
@ -877,6 +919,8 @@ pub fn substring(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultV
Ok(to_value(extracted_string)) Ok(to_value(extracted_string))
} }
/// `String.prototype.substr( start[, length] )`
///
/// The `substr()` method returns a portion of the string, starting at the specified index and extending for a given number of characters afterward. /// The `substr()` method returns a portion of the string, starting at the specified index and extending for a given number of characters afterward.
/// ///
/// More information: /// More information:
@ -933,6 +977,8 @@ pub fn substr(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValu
} }
} }
/// String.prototype.valueOf()
///
/// The `valueOf()` method returns the primitive value of a `String` object. /// The `valueOf()` method returns the primitive value of a `String` object.
/// ///
/// More information: /// More information:
@ -946,6 +992,8 @@ pub fn value_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultVa
to_string(this, args, ctx) to_string(this, args, ctx)
} }
/// `String.prototype.matchAll( regexp )`
///
/// The `matchAll()` method returns an iterator of all results matching a string against a [`regular expression`][regex], including [capturing groups][cg]. /// The `matchAll()` method returns an iterator of all results matching a string against a [`regular expression`][regex], including [capturing groups][cg].
/// ///
/// More information: /// More information:

Loading…
Cancel
Save