@ -17,7 +17,7 @@ use crate::{
builtins ::{
builtins ::{
object ::{ Object , ObjectData } ,
object ::{ Object , ObjectData } ,
property ::Property ,
property ::Property ,
value ::{ ResultValue , Value , ValueData } ,
value ::{ RcString , R esultValue , Value } ,
RegExp ,
RegExp ,
} ,
} ,
exec ::Interpreter ,
exec ::Interpreter ,
@ -28,7 +28,6 @@ use std::string::String as StdString;
use std ::{
use std ::{
cmp ::{ max , min } ,
cmp ::{ max , min } ,
f64 ::NAN ,
f64 ::NAN ,
ops ::Deref ,
} ;
} ;
/// JavaScript `String` implementation.
/// JavaScript `String` implementation.
@ -42,13 +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 ;
fn this_string_value ( this : & Value , ctx : & mut Interpreter ) -> Result < Std String, Value > {
fn this_string_value ( this : & Value , ctx : & mut Interpreter ) -> Result < Rc String, Value > {
match this . data ( ) {
match this {
ValueData ::String ( ref string ) = > return Ok ( string . clone ( ) ) ,
Value ::String ( ref string ) = > return Ok ( string . clone ( ) ) ,
ValueData ::Object ( ref object ) = > {
Value ::Object ( ref object ) = > {
let object = object . borrow ( ) ;
let object = object . borrow ( ) ;
if let Some ( string ) = object . as_string ( ) {
if let Some ( string ) = object . as_string ( ) {
return Ok ( string . to_owned ( ) ) ;
return Ok ( string ) ;
}
}
}
}
_ = > { }
_ = > { }
@ -61,16 +60,12 @@ impl String {
///
///
/// [[Call]] - Returns a new native `string`
/// [[Call]] - Returns a new native `string`
/// <https://tc39.es/ecma262/#sec-string-constructor-string-value>
/// <https://tc39.es/ecma262/#sec-string-constructor-string-value>
pub ( crate ) fn make_string (
pub ( crate ) fn make_string ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut Value ,
args : & [ Value ] ,
ctx : & mut Interpreter ,
) -> ResultValue {
// This value is used by console.log and other routines to match Obexpecty"failed to parse argument for String method"pe
// This value is used by console.log and other routines to match Obexpecty"failed to parse argument for String method"pe
// to its Javascript Identifier (global constructor method name)
// to its Javascript Identifier (global constructor method name)
let string = match args . get ( 0 ) {
let string = match args . get ( 0 ) {
Some ( ref value ) = > ctx . to_string ( value ) ? ,
Some ( ref value ) = > ctx . to_string ( value ) ? ,
None = > StdString ::new ( ) ,
None = > RcString ::default ( ) ,
} ;
} ;
let length = string . chars ( ) . count ( ) ;
let length = string . chars ( ) . count ( ) ;
@ -85,7 +80,7 @@ impl String {
/// Get the string value to a primitive string
/// Get the string value to a primitive string
#[ allow(clippy::wrong_self_convention) ]
#[ allow(clippy::wrong_self_convention) ]
#[ inline ]
#[ inline ]
pub ( crate ) fn to_string ( this : & mut Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn to_string ( this : & Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
// Get String from String Object and send it back as a new value
// Get String from String Object and send it back as a new value
Ok ( Value ::from ( Self ::this_string_value ( this , ctx ) ? ) )
Ok ( Value ::from ( Self ::this_string_value ( this , ctx ) ? ) )
}
}
@ -106,7 +101,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charat
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt
pub ( crate ) fn char_at ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn char_at ( 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -148,11 +143,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charcodeat
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charcodeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
pub ( crate ) fn char_code_at (
pub ( crate ) fn char_code_at ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -192,11 +183,11 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.concat
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat
pub ( crate ) fn concat ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn concat ( 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let object = ctx . require_object_coercible ( this ) ? ;
let object = ctx . require_object_coercible ( this ) ? ;
let mut string = ctx . to_string ( object ) ? ;
let mut string = ctx . to_string ( object ) ? . to_string ( ) ;
for arg in args {
for arg in args {
string . push_str ( & ctx . to_string ( arg ) ? ) ;
string . push_str ( & ctx . to_string ( arg ) ? ) ;
@ -216,7 +207,7 @@ 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 : & mut 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -239,7 +230,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.slice
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.slice
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
pub ( crate ) fn slice ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn slice ( 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -286,11 +277,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.startswith
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.startswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
pub ( crate ) fn starts_with (
pub ( crate ) fn starts_with ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -319,7 +306,7 @@ impl String {
} else {
} else {
// Only use the part of the string from "start"
// Only use the part of the string from "start"
let this_string : StdString = primitive_val . chars ( ) . skip ( start as usize ) . collect ( ) ;
let this_string : StdString = primitive_val . chars ( ) . skip ( start as usize ) . collect ( ) ;
Ok ( Value ::from ( this_string . starts_with ( & search_string ) ) )
Ok ( Value ::from ( this_string . starts_with ( search_string . as_str ( ) ) ) )
}
}
}
}
@ -333,11 +320,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.endswith
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.endswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
pub ( crate ) fn ends_with (
pub ( crate ) fn ends_with ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -367,7 +350,7 @@ impl String {
} else {
} else {
// Only use the part of the string up to "end"
// Only use the part of the string up to "end"
let this_string : StdString = primitive_val . chars ( ) . take ( end as usize ) . collect ( ) ;
let this_string : StdString = primitive_val . chars ( ) . take ( end as usize ) . collect ( ) ;
Ok ( Value ::from ( this_string . ends_with ( & search_string ) ) )
Ok ( Value ::from ( this_string . ends_with ( search_string . as_str ( ) ) ) )
}
}
}
}
@ -381,7 +364,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.includes
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.includes
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
pub ( crate ) fn includes ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn includes ( 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -406,14 +389,14 @@ impl String {
// Take the string from "this" and use only the part of it after "start"
// Take the string from "this" and use only the part of it after "start"
let this_string : StdString = primitive_val . chars ( ) . skip ( start as usize ) . collect ( ) ;
let this_string : StdString = primitive_val . chars ( ) . skip ( start as usize ) . collect ( ) ;
Ok ( Value ::from ( this_string . contains ( & search_string ) ) )
Ok ( Value ::from ( this_string . contains ( search_string . as_str ( ) ) ) )
}
}
/// Return either the string itself or the string of the regex equivalent
/// Return either the string itself or the string of the regex equivalent
fn get_regex_string ( value : & Value ) -> StdString {
fn get_regex_string ( value : & Value ) -> StdString {
match value . deref ( ) {
match value {
ValueData ::String ( ref body ) = > body . into ( ) ,
Value ::String ( ref body ) = > body . to_string ( ) ,
ValueData ::Object ( ref obj ) = > {
Value ::Object ( ref obj ) = > {
let obj = obj . borrow ( ) ;
let obj = obj . borrow ( ) ;
if obj . internal_slots ( ) . get ( "RegExpMatcher" ) . is_some ( ) {
if obj . internal_slots ( ) . get ( "RegExpMatcher" ) . is_some ( ) {
@ -443,7 +426,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.replace
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.replace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
pub ( crate ) fn replace ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn replace ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
// TODO: Support Symbol replacer
// TODO: Support Symbol replacer
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
if args . is_empty ( ) {
if args . is_empty ( ) {
@ -460,8 +443,8 @@ impl String {
let replace_value = if args . len ( ) > 1 {
let replace_value = if args . len ( ) > 1 {
// replace_object could be a string or function or not exist at all
// replace_object could be a string or function or not exist at all
let replace_object : & Value = args . get ( 1 ) . expect ( "second argument expected" ) ;
let replace_object : & Value = args . get ( 1 ) . expect ( "second argument expected" ) ;
match replace_object . deref ( ) {
match replace_object {
ValueData ::String ( val ) = > {
Value ::String ( val ) = > {
// https://tc39.es/ecma262/#table-45
// https://tc39.es/ecma262/#table-45
let mut result = val . to_string ( ) ;
let mut result = val . to_string ( ) ;
let re = Regex ::new ( r"\$(\d)" ) . unwrap ( ) ;
let re = Regex ::new ( r"\$(\d)" ) . unwrap ( ) ;
@ -500,7 +483,7 @@ impl String {
result
result
}
}
ValueData ::Object ( _ ) = > {
Value ::Object ( _ ) = > {
// This will return the matched substring first, then captured parenthesized groups later
// This will return the matched substring first, then captured parenthesized groups later
let mut results : Vec < Value > = caps
let mut results : Vec < Value > = caps
. iter ( )
. iter ( )
@ -518,7 +501,7 @@ impl String {
let result = ctx . call ( & replace_object , this , & results ) . unwrap ( ) ;
let result = ctx . call ( & replace_object , this , & results ) . unwrap ( ) ;
ctx . to_string ( & result ) ?
ctx . to_string ( & result ) ? . to_string ( )
}
}
_ = > "undefined" . to_string ( ) ,
_ = > "undefined" . to_string ( ) ,
}
}
@ -545,7 +528,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.indexof
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.indexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
pub ( crate ) fn index_of ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn index_of ( 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -573,7 +556,7 @@ impl String {
// checking "starts with" the search string
// checking "starts with" the search string
for index in start .. length {
for index in start .. length {
let this_string : StdString = primitive_val . chars ( ) . skip ( index as usize ) . collect ( ) ;
let this_string : StdString = primitive_val . chars ( ) . skip ( index as usize ) . collect ( ) ;
if this_string . starts_with ( & search_string ) {
if this_string . starts_with ( search_string . as_str ( ) ) {
// Explicitly return early with the index value
// Explicitly return early with the index value
return Ok ( Value ::from ( index ) ) ;
return Ok ( Value ::from ( index ) ) ;
}
}
@ -595,7 +578,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.lastindexof
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.lastindexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf
pub ( crate ) fn last_index_of (
pub ( crate ) fn last_index_of (
this : & mut Value ,
this : & Value ,
args : & [ Value ] ,
args : & [ Value ] ,
ctx : & mut Interpreter ,
ctx : & mut Interpreter ,
) -> ResultValue {
) -> ResultValue {
@ -627,7 +610,7 @@ impl String {
let mut highest_index = - 1 ;
let mut highest_index = - 1 ;
for index in start .. length {
for index in start .. length {
let this_string : StdString = primitive_val . chars ( ) . skip ( index as usize ) . collect ( ) ;
let this_string : StdString = primitive_val . chars ( ) . skip ( index as usize ) . collect ( ) ;
if this_string . starts_with ( & search_string ) {
if this_string . starts_with ( search_string . as_str ( ) ) {
highest_index = index ;
highest_index = index ;
}
}
}
}
@ -647,10 +630,9 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.match
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
/// [regex]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
/// [regex]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
pub ( crate ) fn r #match ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn r #match ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
let mut re =
let re = RegExp ::make_regexp ( & Value ::from ( Object ::default ( ) ) , & [ args [ 0 ] . clone ( ) ] , ctx ) ? ;
RegExp ::make_regexp ( & mut Value ::from ( Object ::default ( ) ) , & [ args [ 0 ] . clone ( ) ] , ctx ) ? ;
RegExp ::r#match ( & re , ctx . to_string ( this ) ? , ctx )
RegExp ::r#match ( & mut re , ctx . to_string ( this ) ? , ctx )
}
}
/// Abstract method `StringPad`.
/// Abstract method `StringPad`.
@ -658,9 +640,9 @@ impl String {
/// 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 (
primitive : Std String,
primitive : Rc String,
max_length : i32 ,
max_length : i32 ,
fill_string : Option < Std String> ,
fill_string : Option < Rc String> ,
at_start : bool ,
at_start : bool ,
) -> ResultValue {
) -> ResultValue {
let primitive_length = primitive . len ( ) as i32 ;
let primitive_length = primitive . len ( ) as i32 ;
@ -669,20 +651,13 @@ impl String {
return Ok ( Value ::from ( primitive ) ) ;
return Ok ( Value ::from ( primitive ) ) ;
}
}
let filler = match fill_string {
let filter = fill_string . as_deref ( ) . unwrap_or ( " " ) ;
Some ( filler ) = > filler ,
None = > " " . to_owned ( ) ,
} ;
if filler = = "" {
return Ok ( Value ::from ( primitive ) ) ;
}
let fill_len = max_length . wrapping_sub ( primitive_length ) ;
let fill_len = max_length . wrapping_sub ( primitive_length ) ;
let mut fill_str = StdString ::new ( ) ;
let mut fill_str = StdString ::new ( ) ;
while fill_str . len ( ) < fill_len as usize {
while fill_str . len ( ) < fill_len as usize {
fill_str . push_str ( & fill er) ;
fill_str . push_str ( filter ) ;
}
}
// Cut to size max_length
// Cut to size max_length
let concat_fill_str : StdString = fill_str . chars ( ) . take ( fill_len as usize ) . collect ( ) ;
let concat_fill_str : StdString = fill_str . chars ( ) . take ( fill_len as usize ) . collect ( ) ;
@ -706,8 +681,8 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padend
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
pub ( crate ) fn pad_end ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn pad_end ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
let primitive_val = ctx . to_string ( this ) ? ;
let primitive = ctx . to_string ( this ) ? ;
if args . is_empty ( ) {
if args . is_empty ( ) {
return Err ( Value ::from ( "padEnd requires maxLength argument" ) ) ;
return Err ( Value ::from ( "padEnd requires maxLength argument" ) ) ;
}
}
@ -716,13 +691,9 @@ impl String {
. expect ( "failed to get argument for String method" ) ,
. expect ( "failed to get argument for String method" ) ,
) ;
) ;
let fill_string = if args . len ( ) ! = 1 {
let fill_string = args . get ( 1 ) . map ( | arg | ctx . to_string ( arg ) ) . transpose ( ) ? ;
Some ( ctx . to_string ( args . get ( 1 ) . expect ( "Could not get argument" ) ) ? )
} else {
None
} ;
Self ::string_pad ( primitive_val , max_length , fill_string , false )
Self ::string_pad ( primitive , max_length , fill_string , false )
}
}
/// `String.prototype.padStart( targetLength [, padString] )`
/// `String.prototype.padStart( targetLength [, padString] )`
@ -737,12 +708,8 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padstart
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
pub ( crate ) fn pad_start (
pub ( crate ) fn pad_start ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut Value ,
let primitive = ctx . to_string ( this ) ? ;
args : & [ Value ] ,
ctx : & mut Interpreter ,
) -> ResultValue {
let primitive_val = ctx . to_string ( this ) ? ;
if args . is_empty ( ) {
if args . is_empty ( ) {
return Err ( Value ::from ( "padStart requires maxLength argument" ) ) ;
return Err ( Value ::from ( "padStart requires maxLength argument" ) ) ;
}
}
@ -751,12 +718,9 @@ impl String {
. expect ( "failed to get argument for String method" ) ,
. expect ( "failed to get argument for String method" ) ,
) ;
) ;
let fill_string = match args . len ( ) {
let fill_string = args . get ( 1 ) . map ( | arg | ctx . to_string ( arg ) ) . transpose ( ) ? ;
1 = > None ,
_ = > Some ( ctx . to_string ( args . get ( 1 ) . expect ( "Could not get argument" ) ) ? ) ,
} ;
Self ::string_pad ( primitive_val , max_length , fill_string , true )
Self ::string_pad ( primitive , max_length , fill_string , true )
}
}
/// Helper function to check if a `char` is trimmable.
/// Helper function to check if a `char` is trimmable.
@ -790,7 +754,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trim
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trim
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
pub ( crate ) fn trim ( this : & mut Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn trim ( this : & Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
let this_str = ctx . to_string ( this ) ? ;
let this_str = ctx . to_string ( this ) ? ;
Ok ( Value ::from (
Ok ( Value ::from (
this_str . trim_matches ( Self ::is_trimmable_whitespace ) ,
this_str . trim_matches ( Self ::is_trimmable_whitespace ) ,
@ -809,7 +773,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimstart
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart
pub ( crate ) fn trim_start ( this : & mut Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn trim_start ( this : & Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
let this_str = ctx . to_string ( this ) ? ;
let this_str = ctx . to_string ( this ) ? ;
Ok ( Value ::from (
Ok ( Value ::from (
this_str . trim_start_matches ( Self ::is_trimmable_whitespace ) ,
this_str . trim_start_matches ( Self ::is_trimmable_whitespace ) ,
@ -828,7 +792,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimend
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd
pub ( crate ) fn trim_end ( this : & mut Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn trim_end ( this : & Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
let this_str = ctx . to_string ( this ) ? ;
let this_str = ctx . to_string ( this ) ? ;
Ok ( Value ::from (
Ok ( Value ::from (
this_str . trim_end_matches ( Self ::is_trimmable_whitespace ) ,
this_str . trim_end_matches ( Self ::is_trimmable_whitespace ) ,
@ -846,11 +810,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.tolowercase
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.tolowercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase
#[ allow(clippy::wrong_self_convention) ]
#[ allow(clippy::wrong_self_convention) ]
pub ( crate ) fn to_lowercase (
pub ( crate ) fn to_lowercase ( this : & Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut Value ,
_ : & [ 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let this_str = ctx . to_string ( this ) ? ;
let this_str = ctx . to_string ( this ) ? ;
@ -872,11 +832,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.toUppercase
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.toUppercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase
#[ allow(clippy::wrong_self_convention) ]
#[ allow(clippy::wrong_self_convention) ]
pub ( crate ) fn to_uppercase (
pub ( crate ) fn to_uppercase ( this : & Value , _ : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut Value ,
_ : & [ 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let this_str = ctx . to_string ( this ) ? ;
let this_str = ctx . to_string ( this ) ? ;
@ -895,11 +851,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substring
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring
pub ( crate ) fn substring (
pub ( crate ) fn substring ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -947,7 +899,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substr
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substr
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr
/// <https://tc39.es/ecma262/#sec-string.prototype.substr>
/// <https://tc39.es/ecma262/#sec-string.prototype.substr>
pub ( crate ) fn substr ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn substr ( 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.
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = ctx . to_string ( this ) ? ;
let primitive_val = ctx . to_string ( this ) ? ;
@ -1002,7 +954,7 @@ impl String {
///
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.value_of
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.value_of
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/valueOf
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/valueOf
pub ( crate ) fn value_of ( this : & mut Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
pub ( crate ) fn value_of ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
// Use the to_string method because it is specified to do the same thing in this case
// Use the to_string method because it is specified to do the same thing in this case
Self ::to_string ( this , args , ctx )
Self ::to_string ( this , args , ctx )
}
}
@ -1020,22 +972,18 @@ impl String {
/// [regex]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
/// [regex]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
/// [cg]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges
/// [cg]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges
// TODO: update this method to return iterator
// TODO: update this method to return iterator
pub ( crate ) fn match_all (
pub ( crate ) fn match_all ( this : & Value , args : & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
this : & mut Value ,
let re : Value = match args . get ( 0 ) {
args : & [ Value ] ,
ctx : & mut Interpreter ,
) -> ResultValue {
let mut re : Value = match args . get ( 0 ) {
Some ( arg ) = > {
Some ( arg ) = > {
if arg . is_null ( ) {
if arg . is_null ( ) {
RegExp ::make_regexp (
RegExp ::make_regexp (
& mut Value ::from ( Object ::default ( ) ) ,
& Value ::from ( Object ::default ( ) ) ,
& [ Value ::from ( ctx . to_string ( arg ) ? ) , Value ::from ( "g" ) ] ,
& [ Value ::from ( ctx . to_string ( arg ) ? ) , Value ::from ( "g" ) ] ,
ctx ,
ctx ,
)
)
} else if arg . is_undefined ( ) {
} else if arg . is_undefined ( ) {
RegExp ::make_regexp (
RegExp ::make_regexp (
& mut Value ::from ( Object ::default ( ) ) ,
& Value ::from ( Object ::default ( ) ) ,
& [ Value ::undefined ( ) , Value ::from ( "g" ) ] ,
& [ Value ::undefined ( ) , Value ::from ( "g" ) ] ,
ctx ,
ctx ,
)
)
@ -1044,13 +992,13 @@ impl String {
}
}
}
}
None = > RegExp ::make_regexp (
None = > RegExp ::make_regexp (
& mut Value ::from ( Object ::default ( ) ) ,
& Value ::from ( Object ::default ( ) ) ,
& [ Value ::from ( "" ) , Value ::from ( "g" ) ] ,
& [ Value ::from ( "" ) , Value ::from ( "g" ) ] ,
ctx ,
ctx ,
) ,
) ,
} ? ;
} ? ;
RegExp ::match_all ( & mut re , ctx . to_string ( this ) ? )
RegExp ::match_all ( & re , ctx . to_string ( this ) ? . to_string ( ) )
}
}
/// Create a new `String` object.
/// Create a new `String` object.