Browse Source

added support for char_code_at()

pull/18/head
Jason Williams 5 years ago
parent
commit
78d3cb910d
  1. 21
      .vscode/tasks.json
  2. 34
      src/lib/js/string.rs
  3. 4
      tests/js/test.js

21
.vscode/tasks.json vendored

@ -1,11 +1,11 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "cargo",
"label": "cargo run",
"type": "process",
"label": "Cargo Run",
"command": "cargo",
"args": [
"run"
@ -17,21 +17,6 @@
"kind": "build",
"isDefault": true
}
},
{
"type": "cargo",
"label": "cargo Test",
"command": "cargo",
"args": [
"test"
],
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "test",
"isDefault": true
}
}
]
}

34
src/lib/js/string.rs

@ -2,6 +2,7 @@ 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;
/// Create new string
/// https://searchfox.org/mozilla-central/source/js/src/vm/StringObject.h#19
@ -30,10 +31,10 @@ pub fn to_string(this: Value, _: Value, _: Vec<Value>) -> ResultValue {
Ok(to_value(format!("{}", primitive_val).to_string()))
}
// Get the character at the supplied index
// https://tc39.github.io/ecma262/#sec-string.prototype.charat
/// Get the character at the supplied index
/// https://tc39.github.io/ecma262/#sec-string.prototype.charat
pub fn char_at(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
// ^^ represents instance ^^ represents arguments (we only care about the first one in this case)
// ^^ represents instance ^^ represents arguments (we only care about the first one in this case)
// 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
let primitive_val: String =
@ -45,13 +46,37 @@ pub fn char_at(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
let length = primitive_val.chars().count();
// We should return an empty string is pos is out of range
if pos > length || pos < 0 as usize {
if pos >= length || pos < 0 as usize {
return Ok(to_value::<String>(String::new()));
}
Ok(to_value::<char>(primitive_val.chars().nth(pos).unwrap()))
}
/// Get the character (UTF 16) of string
/// https://tc39.github.io/ecma262/#sec-string.prototype.charcodeat
pub fn char_code_at(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
// ^^ represents instance ^^ represents arguments (we only care about the first one in this case)
// 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
let primitive_val: String =
from_value(this.get_private_field(String::from("PrimitiveValue"))).unwrap();
// Calling .len() on a string would give the wrong result, as they are bytes not the number of unicode code points
// Note that this is an O(N) operation (because UTF-8 is complex) while getting the number of bytes is an O(1) operation.
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();
// If there is no element at that index, the result is NaN
// TODO: We currently don't have NaN
Ok(to_value(utf16_val as f64))
}
/// Create a new `String` object
pub fn _create(global: Value) -> Value {
let string = to_value(make_string as NativeFunctionData);
@ -66,6 +91,7 @@ pub fn _create(global: Value) -> Value {
};
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

4
tests/js/test.js

@ -1,2 +1,2 @@
var a = new String("test");
a.charAt(9);
var a = new String("ABC");
a.charCodeAt(-1);

Loading…
Cancel
Save