1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crate::js::function::NativeFunctionData;
use crate::js::object::{Property, PROTOTYPE};
use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData};
use gc::Gc;
use std::f64::NAN;
pub fn make_string(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
this.set_private_field_slice("PrimitiveValue", args[0].clone());
Ok(this)
}
pub fn get_string_length(this: Value, _: Value, _: Vec<Value>) -> ResultValue {
let this_str: String =
from_value(this.get_private_field(String::from("PrimitiveValue"))).unwrap();
Ok(to_value::<i32>(this_str.len() as i32))
}
pub fn to_string(this: Value, _: Value, _: Vec<Value>) -> ResultValue {
let primitive_val = this.get_private_field(String::from("PrimitiveValue"));
Ok(to_value(format!("{}", primitive_val).to_string()))
}
pub fn char_at(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
let primitive_val: String =
from_value(this.get_private_field(String::from("PrimitiveValue"))).unwrap();
let pos = from_value(args[0].clone()).unwrap();
let length = primitive_val.chars().count();
if pos >= length || pos < 0 as usize {
return Ok(to_value::<String>(String::new()));
}
Ok(to_value::<char>(primitive_val.chars().nth(pos).unwrap()))
}
pub fn char_code_at(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
let primitive_val: String =
from_value(this.get_private_field(String::from("PrimitiveValue"))).unwrap();
let length = primitive_val.chars().count();
let pos = from_value(args[0].clone()).unwrap();
if pos >= length || pos < 0 as usize {
return Ok(to_value(NAN));
}
let utf16_val = primitive_val.encode_utf16().nth(pos).unwrap();
Ok(to_value(utf16_val as f64))
}
pub fn _create(global: &Value) -> Value {
let string = to_value(make_string as NativeFunctionData);
let proto = ValueData::new_obj(Some(global));
let prop = Property {
configurable: false,
enumerable: false,
writable: false,
value: Gc::new(ValueData::Undefined),
get: to_value(get_string_length as NativeFunctionData),
set: Gc::new(ValueData::Undefined),
};
proto.set_prop_slice("length", prop);
proto.set_field_slice("charAt", to_value(char_at as NativeFunctionData));
proto.set_field_slice("charCodeAt", to_value(char_code_at as NativeFunctionData));
proto.set_field_slice("toString", to_value(to_string as NativeFunctionData));
string.set_field_slice(PROTOTYPE, proto);
string
}
pub fn init(global: &Value) {
global.set_field_slice("String", _create(global));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_string_constructor_is_function() {
let global = ValueData::new_obj(None);
let string_constructor = _create(&global);
assert_eq!(string_constructor.is_function(), true);
}
}