mirror of https://github.com/boa-dev/boa.git
Haled Odat
6 months ago
committed by
GitHub
96 changed files with 1750 additions and 1308 deletions
@ -0,0 +1,211 @@
|
||||
//! This module contains the [`js_string`][crate::js_string] macro and the
|
||||
//! [`js_str`][crate::js_str] macro.
|
||||
//!
|
||||
//! The [`js_string`][crate::js_string] macro is used when you need to create a new [`JsString`],
|
||||
//! and the [`js_str`][crate::js_str] macro is used for const conversions of string literals to [`JsStr`].
|
||||
|
||||
#[doc(inline)] |
||||
pub use boa_string::*; |
||||
|
||||
/// Utility macro to create a [`JsString`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// You can call the macro without arguments to create an empty `JsString`:
|
||||
///
|
||||
/// ```
|
||||
/// use boa_engine::js_string;
|
||||
///
|
||||
/// let empty_str = js_string!();
|
||||
/// assert!(empty_str.is_empty());
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// You can create a `JsString` from a string literal, which completely skips the runtime
|
||||
/// conversion from [`&str`] to <code>[&\[u16\]][slice]</code>:
|
||||
///
|
||||
/// ```
|
||||
/// # use boa_engine::js_string;
|
||||
/// let hw = js_string!("Hello, world!");
|
||||
/// assert_eq!(&hw, "Hello, world!");
|
||||
/// ```
|
||||
///
|
||||
/// Any `&[u16]` slice is a valid `JsString`, including unpaired surrogates:
|
||||
///
|
||||
/// ```
|
||||
/// # use boa_engine::js_string;
|
||||
/// let array = js_string!(&[0xD8AFu16, 0x00A0, 0xD8FF, 0x00F0]);
|
||||
/// ```
|
||||
///
|
||||
/// You can also pass it any number of `&[u16]` as arguments to create a new `JsString` with
|
||||
/// the concatenation of every slice:
|
||||
///
|
||||
/// ```
|
||||
/// # use boa_engine::{js_string, js_str, JsStr};
|
||||
/// const NAME: JsStr<'_> = js_str!("human! ");
|
||||
/// let greeting = js_string!("Hello, ");
|
||||
/// let msg = js_string!(&greeting, NAME, js_str!("Nice to meet you!"));
|
||||
///
|
||||
/// assert_eq!(&msg, "Hello, human! Nice to meet you!");
|
||||
/// ```
|
||||
#[macro_export] |
||||
#[allow(clippy::module_name_repetitions)] |
||||
macro_rules! js_string { |
||||
() => { |
||||
$crate::string::JsString::default() |
||||
}; |
||||
($s:literal) => { |
||||
$crate::string::JsString::from($crate::js_str!($s)) |
||||
}; |
||||
($s:expr) => { |
||||
$crate::string::JsString::from($s) |
||||
}; |
||||
( $x:expr, $y:expr ) => { |
||||
$crate::string::JsString::concat($crate::string::JsStr::from($x), $crate::string::JsStr::from($y)) |
||||
}; |
||||
( $( $s:expr ),+ ) => { |
||||
$crate::string::JsString::concat_array(&[ $( $crate::string::JsStr::from($s) ),+ ]) |
||||
}; |
||||
} |
||||
|
||||
#[allow(clippy::redundant_clone)] |
||||
#[cfg(test)] |
||||
mod tests { |
||||
use std::hash::{BuildHasher, BuildHasherDefault, Hash}; |
||||
|
||||
use crate::{string::StaticJsStrings, JsStr}; |
||||
|
||||
use super::JsString; |
||||
use boa_macros::{js_str, utf16}; |
||||
use rustc_hash::FxHasher; |
||||
|
||||
fn hash_value<T: Hash>(value: &T) -> u64 { |
||||
BuildHasherDefault::<FxHasher>::default().hash_one(value) |
||||
} |
||||
|
||||
#[test] |
||||
fn empty() { |
||||
let s = js_string!(); |
||||
assert_eq!(&s, utf16!("")); |
||||
} |
||||
|
||||
#[test] |
||||
fn refcount() { |
||||
let x = js_string!("Hello world"); |
||||
assert_eq!(x.refcount(), Some(1)); |
||||
|
||||
{ |
||||
let y = x.clone(); |
||||
assert_eq!(x.refcount(), Some(2)); |
||||
assert_eq!(y.refcount(), Some(2)); |
||||
|
||||
{ |
||||
let z = y.clone(); |
||||
assert_eq!(x.refcount(), Some(3)); |
||||
assert_eq!(y.refcount(), Some(3)); |
||||
assert_eq!(z.refcount(), Some(3)); |
||||
} |
||||
|
||||
assert_eq!(x.refcount(), Some(2)); |
||||
assert_eq!(y.refcount(), Some(2)); |
||||
} |
||||
|
||||
assert_eq!(x.refcount(), Some(1)); |
||||
} |
||||
|
||||
#[test] |
||||
fn static_refcount() { |
||||
let x = js_string!(); |
||||
assert_eq!(x.refcount(), None); |
||||
|
||||
{ |
||||
let y = x.clone(); |
||||
assert_eq!(x.refcount(), None); |
||||
assert_eq!(y.refcount(), None); |
||||
}; |
||||
|
||||
assert_eq!(x.refcount(), None); |
||||
} |
||||
|
||||
#[test] |
||||
fn as_str() { |
||||
const HELLO: &[u16] = utf16!("Hello"); |
||||
let x = js_string!(HELLO); |
||||
|
||||
assert_eq!(&x, HELLO); |
||||
} |
||||
|
||||
#[test] |
||||
fn hash() { |
||||
const HELLOWORLD: JsStr<'_> = js_str!("Hello World!"); |
||||
let x = js_string!(HELLOWORLD); |
||||
|
||||
assert_eq!(x.as_str(), HELLOWORLD); |
||||
|
||||
assert!(HELLOWORLD.is_latin1()); |
||||
assert!(x.as_str().is_latin1()); |
||||
|
||||
let s_hash = hash_value(&HELLOWORLD); |
||||
let x_hash = hash_value(&x); |
||||
|
||||
assert_eq!(s_hash, x_hash); |
||||
} |
||||
|
||||
#[test] |
||||
fn concat() { |
||||
const Y: &[u16] = utf16!(", "); |
||||
const W: &[u16] = utf16!("!"); |
||||
|
||||
let x = js_string!("hello"); |
||||
let z = js_string!("world"); |
||||
|
||||
let xy = js_string!(&x, &JsString::from(Y)); |
||||
assert_eq!(&xy, utf16!("hello, ")); |
||||
assert_eq!(xy.refcount(), Some(1)); |
||||
|
||||
let xyz = js_string!(&xy, &z); |
||||
assert_eq!(&xyz, utf16!("hello, world")); |
||||
assert_eq!(xyz.refcount(), Some(1)); |
||||
|
||||
let xyzw = js_string!(&xyz, &JsString::from(W)); |
||||
assert_eq!(&xyzw, utf16!("hello, world!")); |
||||
assert_eq!(xyzw.refcount(), Some(1)); |
||||
} |
||||
|
||||
#[test] |
||||
fn trim_start_non_ascii_to_ascii() { |
||||
let s = "\u{2029}abc"; |
||||
let x = js_string!(s); |
||||
|
||||
let y = js_string!(x.trim_start()); |
||||
|
||||
assert_eq!(&y, s.trim_start()); |
||||
} |
||||
|
||||
#[test] |
||||
fn conversion_to_known_static_js_string() { |
||||
const JS_STR_U8: &JsStr<'_> = &js_str!("length"); |
||||
const JS_STR_U16: &JsStr<'_> = &JsStr::utf16(utf16!("length")); |
||||
|
||||
assert!(JS_STR_U8.is_latin1()); |
||||
assert!(!JS_STR_U16.is_latin1()); |
||||
|
||||
assert_eq!(JS_STR_U8, JS_STR_U8); |
||||
assert_eq!(JS_STR_U16, JS_STR_U16); |
||||
|
||||
assert_eq!(JS_STR_U8, JS_STR_U16); |
||||
assert_eq!(JS_STR_U16, JS_STR_U8); |
||||
|
||||
assert_eq!(hash_value(JS_STR_U8), hash_value(JS_STR_U16)); |
||||
|
||||
let string = StaticJsStrings::get_string(JS_STR_U8); |
||||
|
||||
assert!(string.is_some()); |
||||
assert!(string.unwrap().as_str().is_latin1()); |
||||
|
||||
let string = StaticJsStrings::get_string(JS_STR_U16); |
||||
|
||||
assert!(string.is_some()); |
||||
assert!(string.unwrap().as_str().is_latin1()); |
||||
} |
||||
} |
@ -1,950 +0,0 @@
|
||||
//! List of commonly used strings in Javascript code.
|
||||
|
||||
use crate::{tagged::Tagged, JsStr}; |
||||
|
||||
use super::JsString; |
||||
use boa_macros::js_str; |
||||
use paste::paste; |
||||
use rustc_hash::{FxHashMap, FxHasher}; |
||||
use std::hash::BuildHasherDefault; |
||||
|
||||
macro_rules! well_known_statics { |
||||
( $( $(#[$attr:meta])* ($name:ident, $string:literal) ),+$(,)? ) => { |
||||
$( |
||||
paste!{ |
||||
#[doc = "Gets the static `JsString` for `\"" $string "\"`."] |
||||
pub const $name: JsString = JsString { |
||||
ptr: Tagged::from_tag( |
||||
Self::find_index($string), |
||||
), |
||||
}; |
||||
} |
||||
)+ |
||||
}; |
||||
} |
||||
|
||||
/// List of commonly used strings in Javascript code.
|
||||
///
|
||||
/// Any strings defined here are used as a static [`JsString`] instead of allocating on the heap.
|
||||
#[derive(Debug, Clone, Copy)] |
||||
pub struct StaticJsStrings; |
||||
|
||||
impl StaticJsStrings { |
||||
// useful to search at compile time a certain string in the array
|
||||
const fn find_index(candidate: &str) -> usize { |
||||
const fn const_eq(lhs: &[u8], rhs: &[u8]) -> bool { |
||||
if lhs.len() != rhs.len() { |
||||
return false; |
||||
} |
||||
|
||||
let mut i = 0; |
||||
while i < lhs.len() { |
||||
if lhs[i] != rhs[i] { |
||||
return false; |
||||
} |
||||
i += 1; |
||||
} |
||||
true |
||||
} |
||||
|
||||
let len = RAW_STATICS.len(); |
||||
let mut i = 0; |
||||
while i < len { |
||||
let Some(s) = RAW_STATICS[i].as_latin1() else { |
||||
// All static strings are latin1 encoded
|
||||
unreachable!() |
||||
}; |
||||
if const_eq(s, candidate.as_bytes()) { |
||||
return i; |
||||
} |
||||
i += 1; |
||||
} |
||||
|
||||
panic!("couldn't find the required string on the common string array"); |
||||
} |
||||
|
||||
/// Gets the `JsString` corresponding to `string`, or `None` if the string
|
||||
/// doesn't exist inside the static array.
|
||||
pub(crate) fn get_string(string: &JsStr<'_>) -> Option<JsString> { |
||||
if string.len() > MAX_STATIC_LENGTH { |
||||
return None; |
||||
} |
||||
|
||||
let index = RAW_STATICS_CACHE.with(|map| map.get(string).copied())?; |
||||
|
||||
Some(JsString { |
||||
ptr: Tagged::from_tag(index), |
||||
}) |
||||
} |
||||
|
||||
/// Gets the `&[u16]` slice corresponding to the provided index, or `None` if the index
|
||||
/// provided exceeds the size of the static array.
|
||||
pub(crate) fn get(index: usize) -> Option<JsStr<'static>> { |
||||
RAW_STATICS.get(index).copied() |
||||
} |
||||
|
||||
// Some consts are only used on certain features, which triggers the unused lint.
|
||||
well_known_statics! { |
||||
(EMPTY_STRING, ""), |
||||
(LENGTH, "length"), |
||||
// Symbols
|
||||
(SYMBOL_ASYNC_ITERATOR, "Symbol.asyncIterator"), |
||||
(SYMBOL_HAS_INSTANCE, "Symbol.hasInstance"), |
||||
(SYMBOL_IS_CONCAT_SPREADABLE, "Symbol.isConcatSpreadable"), |
||||
(SYMBOL_ITERATOR, "Symbol.iterator"), |
||||
(SYMBOL_MATCH, "Symbol.match"), |
||||
(SYMBOL_MATCH_ALL, "Symbol.matchAll"), |
||||
(SYMBOL_REPLACE, "Symbol.replace"), |
||||
(SYMBOL_SEARCH, "Symbol.search"), |
||||
(SYMBOL_SPECIES, "Symbol.species"), |
||||
(SYMBOL_SPLIT, "Symbol.split"), |
||||
(SYMBOL_TO_PRIMITIVE, "Symbol.toPrimitive"), |
||||
(SYMBOL_TO_STRING_TAG, "Symbol.toStringTag"), |
||||
(SYMBOL_UNSCOPABLES, "Symbol.unscopables"), |
||||
(FN_SYMBOL_ASYNC_ITERATOR, "[Symbol.asyncIterator]"), |
||||
(FN_SYMBOL_HAS_INSTANCE, "[Symbol.hasInstance]"), |
||||
(FN_SYMBOL_IS_CONCAT_SPREADABLE, "[Symbol.isConcatSpreadable]"), |
||||
(FN_SYMBOL_ITERATOR, "[Symbol.iterator]"), |
||||
(FN_SYMBOL_MATCH, "[Symbol.match]"), |
||||
(FN_SYMBOL_MATCH_ALL, "[Symbol.matchAll]"), |
||||
(FN_SYMBOL_REPLACE, "[Symbol.replace]"), |
||||
(FN_SYMBOL_SEARCH, "[Symbol.search]"), |
||||
(FN_SYMBOL_SPECIES, "[Symbol.species]"), |
||||
(FN_SYMBOL_SPLIT, "[Symbol.split]"), |
||||
(FN_SYMBOL_TO_PRIMITIVE, "[Symbol.toPrimitive]"), |
||||
(FN_SYMBOL_TO_STRING_TAG, "[Symbol.toStringTag]"), |
||||
(FN_SYMBOL_UNSCOPABLES, "[Symbol.unscopables]"), |
||||
// Builtins
|
||||
(ARRAY, "Array"), |
||||
(ARRAY_BUFFER, "ArrayBuffer"), |
||||
(SHARED_ARRAY_BUFFER, "SharedArrayBuffer"), |
||||
(ASYNC_FUNCTION, "AsyncFunction"), |
||||
(ASYNC_GENERATOR, "AsyncGenerator"), |
||||
(ASYNC_GENERATOR_FUNCTION, "AsyncGeneratorFunction"), |
||||
(ATOMICS, "Atomics"), |
||||
(BIG_INT, "BigInt"), |
||||
(BOOLEAN, "Boolean"), |
||||
(DATA_VIEW, "DataView"), |
||||
(DATE, "Date"), |
||||
(ERROR, "Error"), |
||||
(AGGREGATE_ERROR, "AggregateError"), |
||||
(EVAL_ERROR, "EvalError"), |
||||
(RANGE_ERROR, "RangeError"), |
||||
(REFERENCE_ERROR, "ReferenceError"), |
||||
(SYNTAX_ERROR, "SyntaxError"), |
||||
(TYPE_ERROR, "TypeError"), |
||||
(URI_ERROR, "URIError"), |
||||
(ESCAPE, "escape"), |
||||
(UNESCAPE, "unescape"), |
||||
(EVAL, "eval"), |
||||
(FUNCTION, "Function"), |
||||
(GENERATOR, "Generator"), |
||||
(GENERATOR_FUNCTION, "GeneratorFunction"), |
||||
(INTL, "Intl"), |
||||
(COLLATOR, "Collator"), |
||||
(LIST_FORMAT, "ListFormat"), |
||||
(LOCALE, "Locale"), |
||||
(PLURAL_RULES, "PluralRules"), |
||||
(SEGMENTER, "Segmenter"), |
||||
(DATE_TIME_FORMAT, "DateTimeFormat"), |
||||
(JSON, "JSON"), |
||||
(MAP, "Map"), |
||||
(MATH, "Math"), |
||||
(NUMBER, "Number"), |
||||
(NUMBER_FORMAT, "NumberFormat"), |
||||
(IS_FINITE, "isFinite"), |
||||
(IS_NAN, "isNaN"), |
||||
(PARSE_INT, "parseInt"), |
||||
(PARSE_FLOAT, "parseFloat"), |
||||
(OBJECT, "Object"), |
||||
(PROMISE, "Promise"), |
||||
(PROXY, "Proxy"), |
||||
(REFLECT, "Reflect"), |
||||
(REG_EXP, "RegExp"), |
||||
(SET, "Set"), |
||||
(STRING, "String"), |
||||
(SYMBOL, "Symbol"), |
||||
(TYPED_ARRAY, "TypedArray"), |
||||
(INT8_ARRAY, "Int8Array"), |
||||
(UINT8_ARRAY, "Uint8Array"), |
||||
(UINT8_CLAMPED_ARRAY, "Uint8ClampedArray"), |
||||
(INT16_ARRAY, "Int16Array"), |
||||
(UINT16_ARRAY, "Uint16Array"), |
||||
(INT32_ARRAY, "Int32Array"), |
||||
(UINT32_ARRAY, "Uint32Array"), |
||||
(BIG_INT64_ARRAY, "BigInt64Array"), |
||||
(BIG_UINT64_ARRAY, "BigUint64Array"), |
||||
(FLOAT32_ARRAY, "Float32Array"), |
||||
(FLOAT64_ARRAY, "Float64Array"), |
||||
(ENCODE_URI, "encodeURI"), |
||||
(ENCODE_URI_COMPONENT, "encodeURIComponent"), |
||||
(DECODE_URI, "decodeURI"), |
||||
(DECODE_URI_COMPONENT, "decodeURIComponent"), |
||||
(WEAK_REF, "WeakRef"), |
||||
(WEAK_MAP, "WeakMap"), |
||||
(WEAK_SET, "WeakSet"), |
||||
(TEMPORAL, "Temporal"), |
||||
(NOW, "Temporal.Now"), |
||||
(INSTANT, "Temporal.Instant"), |
||||
(DURATION, "Temporal.Duration"), |
||||
(PLAIN_DATE, "Temporal.PlainDate"), |
||||
(PLAIN_DATETIME, "Temporal.PlainDateTime"), |
||||
(PLAIN_TIME, "Temporal.PlainTime"), |
||||
(PLAIN_YM, "Temporal.PlainYearMonth"), |
||||
(PLAIN_MD, "Temporal.PlainMonthDay"), |
||||
(CALENDAR, "Temporal.Calendar"), |
||||
(TIMEZONE, "Temporal.TimeZone"), |
||||
(ZONED_DT, "Temporal.ZonedDateTime"), |
||||
} |
||||
} |
||||
|
||||
const MAX_STATIC_LENGTH: usize = { |
||||
let mut max = 0; |
||||
let mut i = 0; |
||||
while i < RAW_STATICS.len() { |
||||
// TOOD: Because `get_index` is not const, we are accessing doc hidden stuff, that may change.
|
||||
let len = RAW_STATICS[i].len(); |
||||
if len > max { |
||||
max = len; |
||||
} |
||||
i += 1; |
||||
} |
||||
max |
||||
}; |
||||
|
||||
thread_local! { |
||||
/// Map from a string inside [`RAW_STATICS`] to its corresponding static index on `RAW_STATICS`.
|
||||
static RAW_STATICS_CACHE: FxHashMap<JsStr<'static>, usize> = { |
||||
let mut constants = FxHashMap::with_capacity_and_hasher( |
||||
RAW_STATICS.len(), |
||||
BuildHasherDefault::<FxHasher>::default(), |
||||
); |
||||
|
||||
for (idx, &s) in RAW_STATICS.iter().enumerate() { |
||||
constants.insert(s, idx); |
||||
} |
||||
|
||||
constants |
||||
}; |
||||
} |
||||
|
||||
/// Array of raw static strings that aren't reference counted.
|
||||
const RAW_STATICS: &[JsStr<'_>] = &[ |
||||
js_str!(""), |
||||
// Well known symbols
|
||||
js_str!("Symbol.asyncIterator"), |
||||
js_str!("[Symbol.asyncIterator]"), |
||||
js_str!("Symbol.hasInstance"), |
||||
js_str!("[Symbol.hasInstance]"), |
||||
js_str!("Symbol.isConcatSpreadable"), |
||||
js_str!("[Symbol.isConcatSpreadable]"), |
||||
js_str!("Symbol.iterator"), |
||||
js_str!("[Symbol.iterator]"), |
||||
js_str!("Symbol.match"), |
||||
js_str!("[Symbol.match]"), |
||||
js_str!("Symbol.matchAll"), |
||||
js_str!("[Symbol.matchAll]"), |
||||
js_str!("Symbol.replace"), |
||||
js_str!("[Symbol.replace]"), |
||||
js_str!("Symbol.search"), |
||||
js_str!("[Symbol.search]"), |
||||
js_str!("Symbol.species"), |
||||
js_str!("[Symbol.species]"), |
||||
js_str!("Symbol.split"), |
||||
js_str!("[Symbol.split]"), |
||||
js_str!("Symbol.toPrimitive"), |
||||
js_str!("[Symbol.toPrimitive]"), |
||||
js_str!("Symbol.toStringTag"), |
||||
js_str!("[Symbol.toStringTag]"), |
||||
js_str!("Symbol.unscopables"), |
||||
js_str!("[Symbol.unscopables]"), |
||||
js_str!("get [Symbol.species]"), |
||||
js_str!("get [Symbol.toStringTag]"), |
||||
// Well known builtins
|
||||
js_str!("Array"), |
||||
js_str!("ArrayBuffer"), |
||||
js_str!("SharedArrayBuffer"), |
||||
js_str!("AsyncFunction"), |
||||
js_str!("AsyncGenerator"), |
||||
js_str!("AsyncGeneratorFunction"), |
||||
js_str!("Atomics"), |
||||
js_str!("BigInt"), |
||||
js_str!("Boolean"), |
||||
js_str!("DataView"), |
||||
js_str!("Date"), |
||||
js_str!("Error"), |
||||
js_str!("AggregateError"), |
||||
js_str!("EvalError"), |
||||
js_str!("RangeError"), |
||||
js_str!("ReferenceError"), |
||||
js_str!("SyntaxError"), |
||||
js_str!("TypeError"), |
||||
js_str!("URIError"), |
||||
js_str!("escape"), |
||||
js_str!("unescape"), |
||||
js_str!("eval"), |
||||
js_str!("Function"), |
||||
js_str!("Generator"), |
||||
js_str!("GeneratorFunction"), |
||||
js_str!("Intl"), |
||||
js_str!("Collator"), |
||||
js_str!("ListFormat"), |
||||
js_str!("Locale"), |
||||
js_str!("PluralRules"), |
||||
js_str!("Segmenter"), |
||||
js_str!("DateTimeFormat"), |
||||
js_str!("JSON"), |
||||
js_str!("Map"), |
||||
js_str!("Math"), |
||||
js_str!("Number"), |
||||
js_str!("NumberFormat"), |
||||
js_str!("isFinite"), |
||||
js_str!("isNaN"), |
||||
js_str!("parseInt"), |
||||
js_str!("parseFloat"), |
||||
js_str!("Object"), |
||||
js_str!("Promise"), |
||||
js_str!("Proxy"), |
||||
js_str!("Reflect"), |
||||
js_str!("RegExp"), |
||||
js_str!("Set"), |
||||
js_str!("String"), |
||||
js_str!("Symbol"), |
||||
js_str!("TypedArray"), |
||||
js_str!("Int8Array"), |
||||
js_str!("Uint8Array"), |
||||
js_str!("Uint8ClampedArray"), |
||||
js_str!("Int16Array"), |
||||
js_str!("Uint16Array"), |
||||
js_str!("Int32Array"), |
||||
js_str!("Uint32Array"), |
||||
js_str!("BigInt64Array"), |
||||
js_str!("BigUint64Array"), |
||||
js_str!("Float32Array"), |
||||
js_str!("Float64Array"), |
||||
js_str!("encodeURI"), |
||||
js_str!("encodeURIComponent"), |
||||
js_str!("decodeURI"), |
||||
js_str!("decodeURIComponent"), |
||||
js_str!("WeakRef"), |
||||
js_str!("WeakMap"), |
||||
js_str!("WeakSet"), |
||||
js_str!("Temporal"), |
||||
js_str!("Temporal.Now"), |
||||
js_str!("Temporal.Instant"), |
||||
js_str!("Temporal.Duration"), |
||||
js_str!("Temporal.Calendar"), |
||||
js_str!("Temporal.PlainDate"), |
||||
js_str!("Temporal.PlainDateTime"), |
||||
js_str!("Temporal.PlainMonthDay"), |
||||
js_str!("Temporal.PlainYearMonth"), |
||||
js_str!("Temporal.PlainTime"), |
||||
js_str!("Temporal.TimeZone"), |
||||
js_str!("Temporal.ZonedDateTime"), |
||||
// Misc
|
||||
js_str!(","), |
||||
js_str!(":"), |
||||
// Generic use
|
||||
js_str!("name"), |
||||
js_str!("length"), |
||||
js_str!("arguments"), |
||||
js_str!("prototype"), |
||||
js_str!("constructor"), |
||||
js_str!("return"), |
||||
js_str!("throw"), |
||||
js_str!("global"), |
||||
js_str!("globalThis"), |
||||
// typeof
|
||||
js_str!("null"), |
||||
js_str!("undefined"), |
||||
js_str!("number"), |
||||
js_str!("string"), |
||||
js_str!("symbol"), |
||||
js_str!("bigint"), |
||||
js_str!("object"), |
||||
js_str!("function"), |
||||
// Property descriptor
|
||||
js_str!("value"), |
||||
js_str!("get"), |
||||
js_str!("set"), |
||||
js_str!("writable"), |
||||
js_str!("enumerable"), |
||||
js_str!("configurable"), |
||||
// Object object
|
||||
js_str!("assign"), |
||||
js_str!("create"), |
||||
js_str!("toString"), |
||||
js_str!("valueOf"), |
||||
js_str!("is"), |
||||
js_str!("seal"), |
||||
js_str!("isSealed"), |
||||
js_str!("freeze"), |
||||
js_str!("isFrozen"), |
||||
js_str!("isExtensible"), |
||||
js_str!("hasOwnProperty"), |
||||
js_str!("isPrototypeOf"), |
||||
js_str!("setPrototypeOf"), |
||||
js_str!("getPrototypeOf"), |
||||
js_str!("defineProperty"), |
||||
js_str!("defineProperties"), |
||||
js_str!("deleteProperty"), |
||||
js_str!("construct"), |
||||
js_str!("hasOwn"), |
||||
js_str!("ownKeys"), |
||||
js_str!("keys"), |
||||
js_str!("values"), |
||||
js_str!("entries"), |
||||
js_str!("fromEntries"), |
||||
js_str!("propertyIsEnumerable"), |
||||
js_str!("preventExtensions"), |
||||
js_str!("getOwnPropertyDescriptor"), |
||||
js_str!("getOwnPropertyDescriptors"), |
||||
js_str!("getOwnPropertyNames"), |
||||
js_str!("getOwnPropertySymbols"), |
||||
js_str!("__defineGetter__"), |
||||
js_str!("__defineSetter__"), |
||||
js_str!("__lookupGetter__"), |
||||
js_str!("__lookupSetter__"), |
||||
js_str!("__proto__"), |
||||
js_str!("get __proto__"), |
||||
js_str!("set __proto__"), |
||||
// Function object
|
||||
js_str!("apply"), |
||||
js_str!("bind"), |
||||
js_str!("call"), |
||||
js_str!("caller"), |
||||
// Arguments object
|
||||
js_str!("callee"), |
||||
// Array object
|
||||
js_str!("at"), |
||||
js_str!("from"), |
||||
js_str!("isArray"), |
||||
js_str!("of"), |
||||
js_str!("copyWithin"), |
||||
js_str!("every"), |
||||
js_str!("fill"), |
||||
js_str!("filter"), |
||||
js_str!("find"), |
||||
js_str!("findIndex"), |
||||
js_str!("findLast"), |
||||
js_str!("findLastIndex"), |
||||
js_str!("flat"), |
||||
js_str!("flatMap"), |
||||
js_str!("forEach"), |
||||
js_str!("includes"), |
||||
js_str!("indexOf"), |
||||
js_str!("join"), |
||||
js_str!("map"), |
||||
js_str!("next"), |
||||
js_str!("reduce"), |
||||
js_str!("reduceRight"), |
||||
js_str!("reverse"), |
||||
js_str!("shift"), |
||||
js_str!("slice"), |
||||
js_str!("splice"), |
||||
js_str!("some"), |
||||
js_str!("sort"), |
||||
js_str!("unshift"), |
||||
js_str!("push"), |
||||
js_str!("pop"), |
||||
js_str!("groupBy"), |
||||
js_str!("toReversed"), |
||||
js_str!("toSorted"), |
||||
js_str!("toSpliced"), |
||||
js_str!("with"), |
||||
// String object
|
||||
js_str!("charAt"), |
||||
js_str!("charCodeAt"), |
||||
js_str!("codePointAt"), |
||||
js_str!("concat"), |
||||
js_str!("endsWith"), |
||||
js_str!("fromCharCode"), |
||||
js_str!("fromCodePoint"), |
||||
js_str!("lastIndexOf"), |
||||
js_str!("match"), |
||||
js_str!("matchAll"), |
||||
js_str!("normalize"), |
||||
js_str!("padEnd"), |
||||
js_str!("padStart"), |
||||
js_str!("raw"), |
||||
js_str!("repeat"), |
||||
js_str!("replace"), |
||||
js_str!("replaceAll"), |
||||
js_str!("search"), |
||||
js_str!("split"), |
||||
js_str!("startsWith"), |
||||
js_str!("substr"), |
||||
js_str!("substring"), |
||||
js_str!("toLocaleString"), |
||||
js_str!("toLowerCase"), |
||||
js_str!("toUpperCase"), |
||||
js_str!("trim"), |
||||
js_str!("trimEnd"), |
||||
js_str!("trimStart"), |
||||
js_str!("isWellFormed"), |
||||
js_str!("localeCompare"), |
||||
js_str!("toWellFormed"), |
||||
js_str!("toLocaleLowerCase"), |
||||
js_str!("toLocaleUpperCase"), |
||||
js_str!("trimLeft"), |
||||
js_str!("trimRight"), |
||||
js_str!("anchor"), |
||||
js_str!("big"), |
||||
js_str!("blink"), |
||||
js_str!("bold"), |
||||
js_str!("fixed"), |
||||
js_str!("fontcolor"), |
||||
js_str!("fontsize"), |
||||
js_str!("italics"), |
||||
js_str!("link"), |
||||
js_str!("small"), |
||||
js_str!("strike"), |
||||
js_str!("sub"), |
||||
js_str!("sup"), |
||||
// Number object
|
||||
js_str!("Infinity"), |
||||
js_str!("NaN"), |
||||
js_str!("EPSILON"), |
||||
js_str!("MAX_SAFE_INTEGER"), |
||||
js_str!("MIN_SAFE_INTEGER"), |
||||
js_str!("MAX_VALUE"), |
||||
js_str!("MIN_VALUE"), |
||||
js_str!("NEGATIVE_INFINITY"), |
||||
js_str!("POSITIVE_INFINITY"), |
||||
js_str!("isSafeInteger"), |
||||
js_str!("isInteger"), |
||||
js_str!("toExponential"), |
||||
js_str!("toFixed"), |
||||
js_str!("toPrecision"), |
||||
// BigInt object
|
||||
js_str!("asIntN"), |
||||
js_str!("asUintN"), |
||||
// RegExp object
|
||||
js_str!("exec"), |
||||
js_str!("test"), |
||||
js_str!("compile"), |
||||
js_str!("flags"), |
||||
js_str!("index"), |
||||
js_str!("lastIndex"), |
||||
js_str!("hasIndices"), |
||||
js_str!("ignoreCase"), |
||||
js_str!("multiline"), |
||||
js_str!("dotAll"), |
||||
js_str!("unicode"), |
||||
js_str!("sticky"), |
||||
js_str!("source"), |
||||
js_str!("get hasIndices"), |
||||
js_str!("get global"), |
||||
js_str!("get ignoreCase"), |
||||
js_str!("get multiline"), |
||||
js_str!("get dotAll"), |
||||
js_str!("get unicode"), |
||||
js_str!("get sticky"), |
||||
js_str!("get flags"), |
||||
js_str!("get source"), |
||||
// Symbol object
|
||||
js_str!("for"), |
||||
js_str!("keyFor"), |
||||
js_str!("description"), |
||||
js_str!("asyncIterator"), |
||||
js_str!("hasInstance"), |
||||
js_str!("species"), |
||||
js_str!("unscopables"), |
||||
js_str!("iterator"), |
||||
js_str!("toStringTag"), |
||||
js_str!("toPrimitive"), |
||||
js_str!("isConcatSpreadable"), |
||||
js_str!("get description"), |
||||
// Map object
|
||||
js_str!("clear"), |
||||
js_str!("delete"), |
||||
js_str!("has"), |
||||
js_str!("size"), |
||||
// Set object
|
||||
js_str!("add"), |
||||
// Reflect object
|
||||
// Proxy object
|
||||
js_str!("revocable"), |
||||
// Error objects
|
||||
js_str!("message"), |
||||
// Date object
|
||||
js_str!("toJSON"), |
||||
js_str!("getDate"), |
||||
js_str!("getDay"), |
||||
js_str!("getFullYear"), |
||||
js_str!("getHours"), |
||||
js_str!("getMilliseconds"), |
||||
js_str!("getMinutes"), |
||||
js_str!("getMonth"), |
||||
js_str!("getSeconds"), |
||||
js_str!("getTime"), |
||||
js_str!("getYear"), |
||||
js_str!("getUTCDate"), |
||||
js_str!("getUTCDay"), |
||||
js_str!("getUTCFullYear"), |
||||
js_str!("getUTCHours"), |
||||
js_str!("getUTCMinutes"), |
||||
js_str!("getUTCMonth"), |
||||
js_str!("getUTCSeconds"), |
||||
js_str!("setDate"), |
||||
js_str!("setFullYear"), |
||||
js_str!("setHours"), |
||||
js_str!("setMilliseconds"), |
||||
js_str!("setMinutes"), |
||||
js_str!("setMonth"), |
||||
js_str!("setSeconds"), |
||||
js_str!("setYear"), |
||||
js_str!("setTime"), |
||||
js_str!("setUTCDate"), |
||||
js_str!("setUTCFullYear"), |
||||
js_str!("setUTCHours"), |
||||
js_str!("setUTCMinutes"), |
||||
js_str!("setUTCMonth"), |
||||
js_str!("setUTCSeconds"), |
||||
js_str!("toDateString"), |
||||
js_str!("toGMTString"), |
||||
js_str!("toISOString"), |
||||
js_str!("toTimeString"), |
||||
js_str!("toUTCString"), |
||||
js_str!("now"), |
||||
js_str!("UTC"), |
||||
js_str!("getTimezoneOffset"), |
||||
js_str!("getUTCMilliseconds"), |
||||
js_str!("setUTCMilliseconds"), |
||||
js_str!("toLocaleDateString"), |
||||
js_str!("toLocaleTimeString"), |
||||
// JSON object
|
||||
js_str!("parse"), |
||||
js_str!("stringify"), |
||||
// Promise object
|
||||
js_str!("promise"), |
||||
js_str!("resolve"), |
||||
js_str!("reject"), |
||||
js_str!("all"), |
||||
js_str!("allSettled"), |
||||
js_str!("any"), |
||||
js_str!("race"), |
||||
js_str!("then"), |
||||
js_str!("catch"), |
||||
js_str!("finally"), |
||||
js_str!("withResolvers"), |
||||
// Iterator object
|
||||
js_str!("Array Iterator"), |
||||
js_str!("Set Iterator"), |
||||
js_str!("String Iterator"), |
||||
js_str!("Map Iterator"), |
||||
js_str!("For In Iterator"), |
||||
js_str!("RegExp String Iterator"), |
||||
// Iterator result object
|
||||
js_str!("done"), |
||||
// Math object
|
||||
js_str!("LN10"), |
||||
js_str!("LN2"), |
||||
js_str!("LOG10E"), |
||||
js_str!("LOG2E"), |
||||
js_str!("PI"), |
||||
js_str!("SQRT1_2"), |
||||
js_str!("SQRT2"), |
||||
js_str!("abs"), |
||||
js_str!("acos"), |
||||
js_str!("acosh"), |
||||
js_str!("asin"), |
||||
js_str!("asinh"), |
||||
js_str!("atan"), |
||||
js_str!("atanh"), |
||||
js_str!("atan2"), |
||||
js_str!("cbrt"), |
||||
js_str!("ceil"), |
||||
js_str!("clz32"), |
||||
js_str!("cos"), |
||||
js_str!("cosh"), |
||||
js_str!("exp"), |
||||
js_str!("expm1"), |
||||
js_str!("floor"), |
||||
js_str!("fround"), |
||||
js_str!("hypot"), |
||||
js_str!("imul"), |
||||
js_str!("log"), |
||||
js_str!("log1p"), |
||||
js_str!("log10"), |
||||
js_str!("log2"), |
||||
js_str!("max"), |
||||
js_str!("min"), |
||||
js_str!("pow"), |
||||
js_str!("random"), |
||||
js_str!("round"), |
||||
js_str!("sign"), |
||||
js_str!("sin"), |
||||
js_str!("sinh"), |
||||
js_str!("sqrt"), |
||||
js_str!("tan"), |
||||
js_str!("tanh"), |
||||
js_str!("trunc"), |
||||
// TypedArray object
|
||||
js_str!("BYTES_PER_ELEMENT"), |
||||
js_str!("buffer"), |
||||
js_str!("byteLength"), |
||||
js_str!("byteOffset"), |
||||
js_str!("isView"), |
||||
js_str!("subarray"), |
||||
js_str!("get byteLength"), |
||||
js_str!("get buffer"), |
||||
js_str!("get byteOffset"), |
||||
js_str!("get size"), |
||||
js_str!("get length"), |
||||
// DataView object
|
||||
js_str!("getBigInt64"), |
||||
js_str!("getBigUint64"), |
||||
js_str!("getFloat32"), |
||||
js_str!("getFloat64"), |
||||
js_str!("getInt8"), |
||||
js_str!("getInt16"), |
||||
js_str!("getInt32"), |
||||
js_str!("getUint8"), |
||||
js_str!("getUint16"), |
||||
js_str!("getUint32"), |
||||
js_str!("setBigInt64"), |
||||
js_str!("setBigUint64"), |
||||
js_str!("setFloat32"), |
||||
js_str!("setFloat64"), |
||||
js_str!("setInt8"), |
||||
js_str!("setInt16"), |
||||
js_str!("setInt32"), |
||||
js_str!("setUint8"), |
||||
js_str!("setUint16"), |
||||
js_str!("setUint32"), |
||||
// WeakRef object
|
||||
js_str!("deref"), |
||||
// Atomic object
|
||||
js_str!("and"), |
||||
js_str!("compareExchange"), |
||||
js_str!("exchange"), |
||||
js_str!("isLockFree"), |
||||
js_str!("load"), |
||||
js_str!("or"), |
||||
js_str!("store"), |
||||
js_str!("wait"), |
||||
js_str!("notify"), |
||||
js_str!("xor"), |
||||
// Intl object
|
||||
js_str!("getCanonicalLocales"), |
||||
js_str!("get compare"), |
||||
js_str!("supportedLocalesOf"), |
||||
js_str!("Intl.Collator"), |
||||
js_str!("compare"), |
||||
js_str!("resolvedOptions"), |
||||
js_str!("Intl.ListFormat"), |
||||
js_str!("format"), |
||||
js_str!("formatToParts"), |
||||
js_str!("get baseName"), |
||||
js_str!("get calendar"), |
||||
js_str!("get caseFirst"), |
||||
js_str!("get collation"), |
||||
js_str!("get hourCycle"), |
||||
js_str!("get numeric"), |
||||
js_str!("get numberingSystem"), |
||||
js_str!("get language"), |
||||
js_str!("get script"), |
||||
js_str!("get region"), |
||||
js_str!("Intl.Locale"), |
||||
js_str!("maximize"), |
||||
js_str!("minimize"), |
||||
js_str!("baseName"), |
||||
js_str!("calendar"), |
||||
js_str!("caseFirst"), |
||||
js_str!("collation"), |
||||
js_str!("hourCycle"), |
||||
js_str!("numeric"), |
||||
js_str!("numberingSystem"), |
||||
js_str!("language"), |
||||
js_str!("script"), |
||||
js_str!("region"), |
||||
js_str!("Intl.Segmenter"), |
||||
js_str!("segment"), |
||||
js_str!("containing"), |
||||
js_str!("Segmenter String Iterator"), |
||||
js_str!("Intl.PluralRules"), |
||||
js_str!("select"), |
||||
// Temporal object
|
||||
js_str!("get Id"), |
||||
js_str!("getOffsetNanosecondsFor"), |
||||
js_str!("getOffsetStringFor"), |
||||
js_str!("getPlainDateTimeFor"), |
||||
js_str!("getInstantFor"), |
||||
js_str!("getPossibleInstantFor"), |
||||
js_str!("getNextTransition"), |
||||
js_str!("getPreviousTransition"), |
||||
js_str!("id"), |
||||
js_str!("Now"), |
||||
js_str!("Calendar"), |
||||
js_str!("Duration"), |
||||
js_str!("Instant"), |
||||
js_str!("PlainDate"), |
||||
js_str!("PlainDateTime"), |
||||
js_str!("PlainMonthDay"), |
||||
js_str!("PlainTime"), |
||||
js_str!("PlainYearMonth"), |
||||
js_str!("TimeZone"), |
||||
js_str!("ZonedDateTime"), |
||||
js_str!("timeZoneId"), |
||||
js_str!("instant"), |
||||
js_str!("plainDateTime"), |
||||
js_str!("plainDateTimeISO"), |
||||
js_str!("zonedDateTime"), |
||||
js_str!("zonedDateTimeISO"), |
||||
js_str!("plainDate"), |
||||
js_str!("plainDateISO"), |
||||
js_str!("get epochSeconds"), |
||||
js_str!("get epochMilliseconds"), |
||||
js_str!("get epochMicroseconds"), |
||||
js_str!("get epochNanoseconds"), |
||||
js_str!("epochSeconds"), |
||||
js_str!("epochMilliseconds"), |
||||
js_str!("epochMicroseconds"), |
||||
js_str!("epochNanoseconds"), |
||||
js_str!("subtract"), |
||||
js_str!("until"), |
||||
js_str!("since"), |
||||
js_str!("equals"), |
||||
js_str!("toZonedDateTime"), |
||||
js_str!("toZonedDateTimeISO"), |
||||
js_str!("get Years"), |
||||
js_str!("get Months"), |
||||
js_str!("get Weeks"), |
||||
js_str!("get Days"), |
||||
js_str!("get Hours"), |
||||
js_str!("get Minutes"), |
||||
js_str!("get Seconds"), |
||||
js_str!("get Milliseconds"), |
||||
js_str!("get Microseconds"), |
||||
js_str!("get Nanoseconds"), |
||||
js_str!("get Sign"), |
||||
js_str!("get blank"), |
||||
js_str!("years"), |
||||
js_str!("months"), |
||||
js_str!("weeks"), |
||||
js_str!("days"), |
||||
js_str!("hours"), |
||||
js_str!("minutes"), |
||||
js_str!("seconds"), |
||||
js_str!("milliseconds"), |
||||
js_str!("microseconds"), |
||||
js_str!("nanoseconds"), |
||||
js_str!("blank"), |
||||
js_str!("negated"), |
||||
js_str!("total"), |
||||
js_str!("get calendarId"), |
||||
js_str!("get year"), |
||||
js_str!("get month"), |
||||
js_str!("get monthCode"), |
||||
js_str!("get day"), |
||||
js_str!("get dayOfWeek"), |
||||
js_str!("get dayOfYear"), |
||||
js_str!("get weekOfYear"), |
||||
js_str!("get yearOfWeek"), |
||||
js_str!("get daysInWeek"), |
||||
js_str!("get daysInMonth"), |
||||
js_str!("get daysInYear"), |
||||
js_str!("get monthsInYear"), |
||||
js_str!("get inLeapYear"), |
||||
js_str!("calendarId"), |
||||
js_str!("year"), |
||||
js_str!("month"), |
||||
js_str!("monthCode"), |
||||
js_str!("day"), |
||||
js_str!("dayOfWeek"), |
||||
js_str!("dayOfYear"), |
||||
js_str!("weekOfYear"), |
||||
js_str!("yearOfWeek"), |
||||
js_str!("daysInWeek"), |
||||
js_str!("daysInMonth"), |
||||
js_str!("daysInYear"), |
||||
js_str!("monthsInYear"), |
||||
js_str!("inLeapYear"), |
||||
js_str!("toPlainYearMonth"), |
||||
js_str!("toPlainMonthDay"), |
||||
js_str!("getISOFields"), |
||||
js_str!("getCalendar"), |
||||
js_str!("withCalendar"), |
||||
js_str!("dateFromFields"), |
||||
js_str!("yearMonthFromFields"), |
||||
js_str!("monthDayFromFields"), |
||||
js_str!("dateAdd"), |
||||
js_str!("dateUntil"), |
||||
js_str!("era"), |
||||
js_str!("eraYear"), |
||||
js_str!("fields"), |
||||
js_str!("mergeFields"), |
||||
// Console object
|
||||
js_str!("console"), |
||||
js_str!("assert"), |
||||
js_str!("debug"), |
||||
js_str!("error"), |
||||
js_str!("info"), |
||||
js_str!("trace"), |
||||
js_str!("warn"), |
||||
js_str!("exception"), |
||||
js_str!("count"), |
||||
js_str!("countReset"), |
||||
js_str!("group"), |
||||
js_str!("groupCollapsed"), |
||||
js_str!("groupEnd"), |
||||
js_str!("time"), |
||||
js_str!("timeLog"), |
||||
js_str!("timeEnd"), |
||||
js_str!("dir"), |
||||
js_str!("dirxml"), |
||||
// Minified name
|
||||
js_str!("a"), |
||||
js_str!("c"), |
||||
js_str!("d"), |
||||
js_str!("e"), |
||||
js_str!("f"), |
||||
js_str!("g"), |
||||
js_str!("h"), |
||||
js_str!("i"), |
||||
js_str!("j"), |
||||
js_str!("k"), |
||||
js_str!("l"), |
||||
js_str!("m"), |
||||
js_str!("n"), |
||||
js_str!("o"), |
||||
js_str!("p"), |
||||
js_str!("q"), |
||||
js_str!("r"), |
||||
js_str!("s"), |
||||
js_str!("t"), |
||||
js_str!("u"), |
||||
js_str!("v"), |
||||
js_str!("w"), |
||||
js_str!("x"), |
||||
js_str!("y"), |
||||
js_str!("z"), |
||||
js_str!("A"), |
||||
js_str!("C"), |
||||
js_str!("D"), |
||||
js_str!("E"), |
||||
js_str!("F"), |
||||
js_str!("G"), |
||||
js_str!("H"), |
||||
js_str!("I"), |
||||
js_str!("J"), |
||||
js_str!("K"), |
||||
js_str!("L"), |
||||
js_str!("M"), |
||||
js_str!("N"), |
||||
js_str!("O"), |
||||
js_str!("P"), |
||||
js_str!("Q"), |
||||
js_str!("R"), |
||||
js_str!("S"), |
||||
js_str!("T"), |
||||
js_str!("U"), |
||||
js_str!("V"), |
||||
js_str!("W"), |
||||
js_str!("X"), |
||||
js_str!("Y"), |
||||
js_str!("Z"), |
||||
js_str!("_"), |
||||
js_str!("$"), |
||||
]; |
@ -0,0 +1,34 @@
|
||||
# About Boa |
||||
|
||||
Boa is an open-source, experimental ECMAScript Engine written in Rust for |
||||
lexing, parsing and executing ECMAScript/JavaScript. Currently, Boa supports some |
||||
of the [language][boa-conformance]. More information can be viewed at [Boa's |
||||
website][boa-web]. |
||||
|
||||
Try out the most recent release with Boa's live demo |
||||
[playground][boa-playground]. |
||||
|
||||
## Boa Crates |
||||
|
||||
- [**`boa_ast`**][ast] - Boa's ECMAScript Abstract Syntax Tree. |
||||
- [**`boa_engine`**][engine] - Boa's implementation of ECMAScript builtin objects and execution. |
||||
- [**`boa_gc`**][gc] - Boa's garbage collector. |
||||
- [**`boa_interner`**][interner] - Boa's string interner. |
||||
- [**`boa_parser`**][parser] - Boa's lexer and parser. |
||||
- [**`boa_profiler`**][profiler] - Boa's code profiler. |
||||
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider. |
||||
- [**`boa_runtime`**][runtime] - Boa's WebAPI features. |
||||
- [**`boa_string`**][string] - Boa's ECMAScript string implementation. |
||||
|
||||
[boa-conformance]: https://boajs.dev/conformance |
||||
[boa-web]: https://boajs.dev/ |
||||
[boa-playground]: https://boajs.dev/playground |
||||
[ast]: https://docs.rs/boa_ast/latest/boa_ast/index.html |
||||
[engine]: https://docs.rs/boa_engine/latest/boa_engine/index.html |
||||
[gc]: https://docs.rs/boa_gc/latest/boa_gc/index.html |
||||
[interner]: https://docs.rs/boa_interner/latest/boa_interner/index.html |
||||
[parser]: https://docs.rs/boa_parser/latest/boa_parser/index.html |
||||
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html |
||||
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html |
||||
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html |
||||
[string]: https://docs.rs/boa_string/latest/boa_string/index.html |
@ -0,0 +1,28 @@
|
||||
[package] |
||||
name = "boa_string" |
||||
keywords = ["javascript", "js", "string"] |
||||
categories = ["parser-implementations", "compilers"] |
||||
readme = "../../README.md" |
||||
description.workspace = true |
||||
version.workspace = true |
||||
edition.workspace = true |
||||
authors.workspace = true |
||||
license.workspace = true |
||||
repository.workspace = true |
||||
rust-version.workspace = true |
||||
|
||||
[dependencies] |
||||
rustc-hash = { workspace = true, features = ["std"] } |
||||
sptr = "0.3.2" |
||||
static_assertions.workspace = true |
||||
paste = "1.0" |
||||
fast-float.workspace = true |
||||
|
||||
[dev-dependencies] |
||||
boa_macros.workspace = true |
||||
|
||||
[lints] |
||||
workspace = true |
||||
|
||||
[package.metadata.docs.rs] |
||||
all-features = true |
@ -0,0 +1,951 @@
|
||||
//! List of commonly used strings in Javascript code.
|
||||
|
||||
use crate::{tagged::Tagged, JsStr}; |
||||
|
||||
use super::JsString; |
||||
use paste::paste; |
||||
use rustc_hash::{FxHashMap, FxHasher}; |
||||
use std::hash::BuildHasherDefault; |
||||
|
||||
macro_rules! well_known_statics { |
||||
( $( $(#[$attr:meta])* ($name:ident, $string:literal) ),+$(,)? ) => { |
||||
$( |
||||
paste!{ |
||||
#[doc = "Gets the static `JsString` for `\"" $string "\"`."] |
||||
pub const $name: JsString = JsString { |
||||
ptr: Tagged::from_tag( |
||||
Self::find_index($string), |
||||
), |
||||
}; |
||||
} |
||||
)+ |
||||
}; |
||||
} |
||||
|
||||
/// List of commonly used strings in Javascript code.
|
||||
///
|
||||
/// Any strings defined here are used as a static [`JsString`] instead of allocating on the heap.
|
||||
#[derive(Debug, Clone, Copy)] |
||||
pub struct StaticJsStrings; |
||||
|
||||
impl StaticJsStrings { |
||||
// useful to search at compile time a certain string in the array
|
||||
const fn find_index(candidate: &str) -> usize { |
||||
const fn const_eq(lhs: &[u8], rhs: &[u8]) -> bool { |
||||
if lhs.len() != rhs.len() { |
||||
return false; |
||||
} |
||||
|
||||
let mut i = 0; |
||||
while i < lhs.len() { |
||||
if lhs[i] != rhs[i] { |
||||
return false; |
||||
} |
||||
i += 1; |
||||
} |
||||
true |
||||
} |
||||
|
||||
let len = RAW_STATICS.len(); |
||||
let mut i = 0; |
||||
while i < len { |
||||
let Some(s) = RAW_STATICS[i].as_latin1() else { |
||||
// All static strings are latin1 encoded
|
||||
unreachable!() |
||||
}; |
||||
if const_eq(s, candidate.as_bytes()) { |
||||
return i; |
||||
} |
||||
i += 1; |
||||
} |
||||
|
||||
panic!("couldn't find the required string on the common string array"); |
||||
} |
||||
|
||||
/// Gets the `JsString` corresponding to `string`, or `None` if the string
|
||||
/// doesn't exist inside the static array.
|
||||
#[inline] |
||||
#[must_use] |
||||
pub fn get_string(string: &JsStr<'_>) -> Option<JsString> { |
||||
if string.len() > MAX_STATIC_LENGTH { |
||||
return None; |
||||
} |
||||
|
||||
let index = RAW_STATICS_CACHE.with(|map| map.get(string).copied())?; |
||||
|
||||
Some(JsString { |
||||
ptr: Tagged::from_tag(index), |
||||
}) |
||||
} |
||||
|
||||
/// Gets the `&[u16]` slice corresponding to the provided index, or `None` if the index
|
||||
/// provided exceeds the size of the static array.
|
||||
pub(crate) fn get(index: usize) -> Option<JsStr<'static>> { |
||||
RAW_STATICS.get(index).copied() |
||||
} |
||||
|
||||
// Some consts are only used on certain features, which triggers the unused lint.
|
||||
well_known_statics! { |
||||
(EMPTY_STRING, ""), |
||||
(LENGTH, "length"), |
||||
// Symbols
|
||||
(SYMBOL_ASYNC_ITERATOR, "Symbol.asyncIterator"), |
||||
(SYMBOL_HAS_INSTANCE, "Symbol.hasInstance"), |
||||
(SYMBOL_IS_CONCAT_SPREADABLE, "Symbol.isConcatSpreadable"), |
||||
(SYMBOL_ITERATOR, "Symbol.iterator"), |
||||
(SYMBOL_MATCH, "Symbol.match"), |
||||
(SYMBOL_MATCH_ALL, "Symbol.matchAll"), |
||||
(SYMBOL_REPLACE, "Symbol.replace"), |
||||
(SYMBOL_SEARCH, "Symbol.search"), |
||||
(SYMBOL_SPECIES, "Symbol.species"), |
||||
(SYMBOL_SPLIT, "Symbol.split"), |
||||
(SYMBOL_TO_PRIMITIVE, "Symbol.toPrimitive"), |
||||
(SYMBOL_TO_STRING_TAG, "Symbol.toStringTag"), |
||||
(SYMBOL_UNSCOPABLES, "Symbol.unscopables"), |
||||
(FN_SYMBOL_ASYNC_ITERATOR, "[Symbol.asyncIterator]"), |
||||
(FN_SYMBOL_HAS_INSTANCE, "[Symbol.hasInstance]"), |
||||
(FN_SYMBOL_IS_CONCAT_SPREADABLE, "[Symbol.isConcatSpreadable]"), |
||||
(FN_SYMBOL_ITERATOR, "[Symbol.iterator]"), |
||||
(FN_SYMBOL_MATCH, "[Symbol.match]"), |
||||
(FN_SYMBOL_MATCH_ALL, "[Symbol.matchAll]"), |
||||
(FN_SYMBOL_REPLACE, "[Symbol.replace]"), |
||||
(FN_SYMBOL_SEARCH, "[Symbol.search]"), |
||||
(FN_SYMBOL_SPECIES, "[Symbol.species]"), |
||||
(FN_SYMBOL_SPLIT, "[Symbol.split]"), |
||||
(FN_SYMBOL_TO_PRIMITIVE, "[Symbol.toPrimitive]"), |
||||
(FN_SYMBOL_TO_STRING_TAG, "[Symbol.toStringTag]"), |
||||
(FN_SYMBOL_UNSCOPABLES, "[Symbol.unscopables]"), |
||||
// Builtins
|
||||
(ARRAY, "Array"), |
||||
(ARRAY_BUFFER, "ArrayBuffer"), |
||||
(SHARED_ARRAY_BUFFER, "SharedArrayBuffer"), |
||||
(ASYNC_FUNCTION, "AsyncFunction"), |
||||
(ASYNC_GENERATOR, "AsyncGenerator"), |
||||
(ASYNC_GENERATOR_FUNCTION, "AsyncGeneratorFunction"), |
||||
(ATOMICS, "Atomics"), |
||||
(BIG_INT, "BigInt"), |
||||
(BOOLEAN, "Boolean"), |
||||
(DATA_VIEW, "DataView"), |
||||
(DATE, "Date"), |
||||
(ERROR, "Error"), |
||||
(AGGREGATE_ERROR, "AggregateError"), |
||||
(EVAL_ERROR, "EvalError"), |
||||
(RANGE_ERROR, "RangeError"), |
||||
(REFERENCE_ERROR, "ReferenceError"), |
||||
(SYNTAX_ERROR, "SyntaxError"), |
||||
(TYPE_ERROR, "TypeError"), |
||||
(URI_ERROR, "URIError"), |
||||
(ESCAPE, "escape"), |
||||
(UNESCAPE, "unescape"), |
||||
(EVAL, "eval"), |
||||
(FUNCTION, "Function"), |
||||
(GENERATOR, "Generator"), |
||||
(GENERATOR_FUNCTION, "GeneratorFunction"), |
||||
(INTL, "Intl"), |
||||
(COLLATOR, "Collator"), |
||||
(LIST_FORMAT, "ListFormat"), |
||||
(LOCALE, "Locale"), |
||||
(PLURAL_RULES, "PluralRules"), |
||||
(SEGMENTER, "Segmenter"), |
||||
(DATE_TIME_FORMAT, "DateTimeFormat"), |
||||
(JSON, "JSON"), |
||||
(MAP, "Map"), |
||||
(MATH, "Math"), |
||||
(NUMBER, "Number"), |
||||
(NUMBER_FORMAT, "NumberFormat"), |
||||
(IS_FINITE, "isFinite"), |
||||
(IS_NAN, "isNaN"), |
||||
(PARSE_INT, "parseInt"), |
||||
(PARSE_FLOAT, "parseFloat"), |
||||
(OBJECT, "Object"), |
||||
(PROMISE, "Promise"), |
||||
(PROXY, "Proxy"), |
||||
(REFLECT, "Reflect"), |
||||
(REG_EXP, "RegExp"), |
||||
(SET, "Set"), |
||||
(STRING, "String"), |
||||
(SYMBOL, "Symbol"), |
||||
(TYPED_ARRAY, "TypedArray"), |
||||
(INT8_ARRAY, "Int8Array"), |
||||
(UINT8_ARRAY, "Uint8Array"), |
||||
(UINT8_CLAMPED_ARRAY, "Uint8ClampedArray"), |
||||
(INT16_ARRAY, "Int16Array"), |
||||
(UINT16_ARRAY, "Uint16Array"), |
||||
(INT32_ARRAY, "Int32Array"), |
||||
(UINT32_ARRAY, "Uint32Array"), |
||||
(BIG_INT64_ARRAY, "BigInt64Array"), |
||||
(BIG_UINT64_ARRAY, "BigUint64Array"), |
||||
(FLOAT32_ARRAY, "Float32Array"), |
||||
(FLOAT64_ARRAY, "Float64Array"), |
||||
(ENCODE_URI, "encodeURI"), |
||||
(ENCODE_URI_COMPONENT, "encodeURIComponent"), |
||||
(DECODE_URI, "decodeURI"), |
||||
(DECODE_URI_COMPONENT, "decodeURIComponent"), |
||||
(WEAK_REF, "WeakRef"), |
||||
(WEAK_MAP, "WeakMap"), |
||||
(WEAK_SET, "WeakSet"), |
||||
(TEMPORAL, "Temporal"), |
||||
(NOW, "Temporal.Now"), |
||||
(INSTANT, "Temporal.Instant"), |
||||
(DURATION, "Temporal.Duration"), |
||||
(PLAIN_DATE, "Temporal.PlainDate"), |
||||
(PLAIN_DATETIME, "Temporal.PlainDateTime"), |
||||
(PLAIN_TIME, "Temporal.PlainTime"), |
||||
(PLAIN_YM, "Temporal.PlainYearMonth"), |
||||
(PLAIN_MD, "Temporal.PlainMonthDay"), |
||||
(CALENDAR, "Temporal.Calendar"), |
||||
(TIMEZONE, "Temporal.TimeZone"), |
||||
(ZONED_DT, "Temporal.ZonedDateTime"), |
||||
} |
||||
} |
||||
|
||||
const MAX_STATIC_LENGTH: usize = { |
||||
let mut max = 0; |
||||
let mut i = 0; |
||||
while i < RAW_STATICS.len() { |
||||
// TOOD: Because `get_index` is not const, we are accessing doc hidden stuff, that may change.
|
||||
let len = RAW_STATICS[i].len(); |
||||
if len > max { |
||||
max = len; |
||||
} |
||||
i += 1; |
||||
} |
||||
max |
||||
}; |
||||
|
||||
thread_local! { |
||||
/// Map from a string inside [`RAW_STATICS`] to its corresponding static index on `RAW_STATICS`.
|
||||
static RAW_STATICS_CACHE: FxHashMap<JsStr<'static>, usize> = { |
||||
let mut constants = FxHashMap::with_capacity_and_hasher( |
||||
RAW_STATICS.len(), |
||||
BuildHasherDefault::<FxHasher>::default(), |
||||
); |
||||
|
||||
for (idx, &s) in RAW_STATICS.iter().enumerate() { |
||||
constants.insert(s, idx); |
||||
} |
||||
|
||||
constants |
||||
}; |
||||
} |
||||
|
||||
/// Array of raw static strings that aren't reference counted.
|
||||
const RAW_STATICS: &[JsStr<'_>] = &[ |
||||
JsStr::latin1("".as_bytes()), |
||||
// Well known symbols
|
||||
JsStr::latin1("Symbol.asyncIterator".as_bytes()), |
||||
JsStr::latin1("[Symbol.asyncIterator]".as_bytes()), |
||||
JsStr::latin1("Symbol.hasInstance".as_bytes()), |
||||
JsStr::latin1("[Symbol.hasInstance]".as_bytes()), |
||||
JsStr::latin1("Symbol.isConcatSpreadable".as_bytes()), |
||||
JsStr::latin1("[Symbol.isConcatSpreadable]".as_bytes()), |
||||
JsStr::latin1("Symbol.iterator".as_bytes()), |
||||
JsStr::latin1("[Symbol.iterator]".as_bytes()), |
||||
JsStr::latin1("Symbol.match".as_bytes()), |
||||
JsStr::latin1("[Symbol.match]".as_bytes()), |
||||
JsStr::latin1("Symbol.matchAll".as_bytes()), |
||||
JsStr::latin1("[Symbol.matchAll]".as_bytes()), |
||||
JsStr::latin1("Symbol.replace".as_bytes()), |
||||
JsStr::latin1("[Symbol.replace]".as_bytes()), |
||||
JsStr::latin1("Symbol.search".as_bytes()), |
||||
JsStr::latin1("[Symbol.search]".as_bytes()), |
||||
JsStr::latin1("Symbol.species".as_bytes()), |
||||
JsStr::latin1("[Symbol.species]".as_bytes()), |
||||
JsStr::latin1("Symbol.split".as_bytes()), |
||||
JsStr::latin1("[Symbol.split]".as_bytes()), |
||||
JsStr::latin1("Symbol.toPrimitive".as_bytes()), |
||||
JsStr::latin1("[Symbol.toPrimitive]".as_bytes()), |
||||
JsStr::latin1("Symbol.toStringTag".as_bytes()), |
||||
JsStr::latin1("[Symbol.toStringTag]".as_bytes()), |
||||
JsStr::latin1("Symbol.unscopables".as_bytes()), |
||||
JsStr::latin1("[Symbol.unscopables]".as_bytes()), |
||||
JsStr::latin1("get [Symbol.species]".as_bytes()), |
||||
JsStr::latin1("get [Symbol.toStringTag]".as_bytes()), |
||||
// Well known builtins
|
||||
JsStr::latin1("Array".as_bytes()), |
||||
JsStr::latin1("ArrayBuffer".as_bytes()), |
||||
JsStr::latin1("SharedArrayBuffer".as_bytes()), |
||||
JsStr::latin1("AsyncFunction".as_bytes()), |
||||
JsStr::latin1("AsyncGenerator".as_bytes()), |
||||
JsStr::latin1("AsyncGeneratorFunction".as_bytes()), |
||||
JsStr::latin1("Atomics".as_bytes()), |
||||
JsStr::latin1("BigInt".as_bytes()), |
||||
JsStr::latin1("Boolean".as_bytes()), |
||||
JsStr::latin1("DataView".as_bytes()), |
||||
JsStr::latin1("Date".as_bytes()), |
||||
JsStr::latin1("Error".as_bytes()), |
||||
JsStr::latin1("AggregateError".as_bytes()), |
||||
JsStr::latin1("EvalError".as_bytes()), |
||||
JsStr::latin1("RangeError".as_bytes()), |
||||
JsStr::latin1("ReferenceError".as_bytes()), |
||||
JsStr::latin1("SyntaxError".as_bytes()), |
||||
JsStr::latin1("TypeError".as_bytes()), |
||||
JsStr::latin1("URIError".as_bytes()), |
||||
JsStr::latin1("escape".as_bytes()), |
||||
JsStr::latin1("unescape".as_bytes()), |
||||
JsStr::latin1("eval".as_bytes()), |
||||
JsStr::latin1("Function".as_bytes()), |
||||
JsStr::latin1("Generator".as_bytes()), |
||||
JsStr::latin1("GeneratorFunction".as_bytes()), |
||||
JsStr::latin1("Intl".as_bytes()), |
||||
JsStr::latin1("Collator".as_bytes()), |
||||
JsStr::latin1("ListFormat".as_bytes()), |
||||
JsStr::latin1("Locale".as_bytes()), |
||||
JsStr::latin1("PluralRules".as_bytes()), |
||||
JsStr::latin1("Segmenter".as_bytes()), |
||||
JsStr::latin1("DateTimeFormat".as_bytes()), |
||||
JsStr::latin1("JSON".as_bytes()), |
||||
JsStr::latin1("Map".as_bytes()), |
||||
JsStr::latin1("Math".as_bytes()), |
||||
JsStr::latin1("Number".as_bytes()), |
||||
JsStr::latin1("NumberFormat".as_bytes()), |
||||
JsStr::latin1("isFinite".as_bytes()), |
||||
JsStr::latin1("isNaN".as_bytes()), |
||||
JsStr::latin1("parseInt".as_bytes()), |
||||
JsStr::latin1("parseFloat".as_bytes()), |
||||
JsStr::latin1("Object".as_bytes()), |
||||
JsStr::latin1("Promise".as_bytes()), |
||||
JsStr::latin1("Proxy".as_bytes()), |
||||
JsStr::latin1("Reflect".as_bytes()), |
||||
JsStr::latin1("RegExp".as_bytes()), |
||||
JsStr::latin1("Set".as_bytes()), |
||||
JsStr::latin1("String".as_bytes()), |
||||
JsStr::latin1("Symbol".as_bytes()), |
||||
JsStr::latin1("TypedArray".as_bytes()), |
||||
JsStr::latin1("Int8Array".as_bytes()), |
||||
JsStr::latin1("Uint8Array".as_bytes()), |
||||
JsStr::latin1("Uint8ClampedArray".as_bytes()), |
||||
JsStr::latin1("Int16Array".as_bytes()), |
||||
JsStr::latin1("Uint16Array".as_bytes()), |
||||
JsStr::latin1("Int32Array".as_bytes()), |
||||
JsStr::latin1("Uint32Array".as_bytes()), |
||||
JsStr::latin1("BigInt64Array".as_bytes()), |
||||
JsStr::latin1("BigUint64Array".as_bytes()), |
||||
JsStr::latin1("Float32Array".as_bytes()), |
||||
JsStr::latin1("Float64Array".as_bytes()), |
||||
JsStr::latin1("encodeURI".as_bytes()), |
||||
JsStr::latin1("encodeURIComponent".as_bytes()), |
||||
JsStr::latin1("decodeURI".as_bytes()), |
||||
JsStr::latin1("decodeURIComponent".as_bytes()), |
||||
JsStr::latin1("WeakRef".as_bytes()), |
||||
JsStr::latin1("WeakMap".as_bytes()), |
||||
JsStr::latin1("WeakSet".as_bytes()), |
||||
JsStr::latin1("Temporal".as_bytes()), |
||||
JsStr::latin1("Temporal.Now".as_bytes()), |
||||
JsStr::latin1("Temporal.Instant".as_bytes()), |
||||
JsStr::latin1("Temporal.Duration".as_bytes()), |
||||
JsStr::latin1("Temporal.Calendar".as_bytes()), |
||||
JsStr::latin1("Temporal.PlainDate".as_bytes()), |
||||
JsStr::latin1("Temporal.PlainDateTime".as_bytes()), |
||||
JsStr::latin1("Temporal.PlainMonthDay".as_bytes()), |
||||
JsStr::latin1("Temporal.PlainYearMonth".as_bytes()), |
||||
JsStr::latin1("Temporal.PlainTime".as_bytes()), |
||||
JsStr::latin1("Temporal.TimeZone".as_bytes()), |
||||
JsStr::latin1("Temporal.ZonedDateTime".as_bytes()), |
||||
// Misc
|
||||
JsStr::latin1(",".as_bytes()), |
||||
JsStr::latin1(":".as_bytes()), |
||||
// Generic use
|
||||
JsStr::latin1("name".as_bytes()), |
||||
JsStr::latin1("length".as_bytes()), |
||||
JsStr::latin1("arguments".as_bytes()), |
||||
JsStr::latin1("prototype".as_bytes()), |
||||
JsStr::latin1("constructor".as_bytes()), |
||||
JsStr::latin1("return".as_bytes()), |
||||
JsStr::latin1("throw".as_bytes()), |
||||
JsStr::latin1("global".as_bytes()), |
||||
JsStr::latin1("globalThis".as_bytes()), |
||||
// typeof
|
||||
JsStr::latin1("null".as_bytes()), |
||||
JsStr::latin1("undefined".as_bytes()), |
||||
JsStr::latin1("number".as_bytes()), |
||||
JsStr::latin1("string".as_bytes()), |
||||
JsStr::latin1("symbol".as_bytes()), |
||||
JsStr::latin1("bigint".as_bytes()), |
||||
JsStr::latin1("object".as_bytes()), |
||||
JsStr::latin1("function".as_bytes()), |
||||
// Property descriptor
|
||||
JsStr::latin1("value".as_bytes()), |
||||
JsStr::latin1("get".as_bytes()), |
||||
JsStr::latin1("set".as_bytes()), |
||||
JsStr::latin1("writable".as_bytes()), |
||||
JsStr::latin1("enumerable".as_bytes()), |
||||
JsStr::latin1("configurable".as_bytes()), |
||||
// Object object
|
||||
JsStr::latin1("assign".as_bytes()), |
||||
JsStr::latin1("create".as_bytes()), |
||||
JsStr::latin1("toString".as_bytes()), |
||||
JsStr::latin1("valueOf".as_bytes()), |
||||
JsStr::latin1("is".as_bytes()), |
||||
JsStr::latin1("seal".as_bytes()), |
||||
JsStr::latin1("isSealed".as_bytes()), |
||||
JsStr::latin1("freeze".as_bytes()), |
||||
JsStr::latin1("isFrozen".as_bytes()), |
||||
JsStr::latin1("isExtensible".as_bytes()), |
||||
JsStr::latin1("hasOwnProperty".as_bytes()), |
||||
JsStr::latin1("isPrototypeOf".as_bytes()), |
||||
JsStr::latin1("setPrototypeOf".as_bytes()), |
||||
JsStr::latin1("getPrototypeOf".as_bytes()), |
||||
JsStr::latin1("defineProperty".as_bytes()), |
||||
JsStr::latin1("defineProperties".as_bytes()), |
||||
JsStr::latin1("deleteProperty".as_bytes()), |
||||
JsStr::latin1("construct".as_bytes()), |
||||
JsStr::latin1("hasOwn".as_bytes()), |
||||
JsStr::latin1("ownKeys".as_bytes()), |
||||
JsStr::latin1("keys".as_bytes()), |
||||
JsStr::latin1("values".as_bytes()), |
||||
JsStr::latin1("entries".as_bytes()), |
||||
JsStr::latin1("fromEntries".as_bytes()), |
||||
JsStr::latin1("propertyIsEnumerable".as_bytes()), |
||||
JsStr::latin1("preventExtensions".as_bytes()), |
||||
JsStr::latin1("getOwnPropertyDescriptor".as_bytes()), |
||||
JsStr::latin1("getOwnPropertyDescriptors".as_bytes()), |
||||
JsStr::latin1("getOwnPropertyNames".as_bytes()), |
||||
JsStr::latin1("getOwnPropertySymbols".as_bytes()), |
||||
JsStr::latin1("__defineGetter__".as_bytes()), |
||||
JsStr::latin1("__defineSetter__".as_bytes()), |
||||
JsStr::latin1("__lookupGetter__".as_bytes()), |
||||
JsStr::latin1("__lookupSetter__".as_bytes()), |
||||
JsStr::latin1("__proto__".as_bytes()), |
||||
JsStr::latin1("get __proto__".as_bytes()), |
||||
JsStr::latin1("set __proto__".as_bytes()), |
||||
// Function object
|
||||
JsStr::latin1("apply".as_bytes()), |
||||
JsStr::latin1("bind".as_bytes()), |
||||
JsStr::latin1("call".as_bytes()), |
||||
JsStr::latin1("caller".as_bytes()), |
||||
// Arguments object
|
||||
JsStr::latin1("callee".as_bytes()), |
||||
// Array object
|
||||
JsStr::latin1("at".as_bytes()), |
||||
JsStr::latin1("from".as_bytes()), |
||||
JsStr::latin1("isArray".as_bytes()), |
||||
JsStr::latin1("of".as_bytes()), |
||||
JsStr::latin1("copyWithin".as_bytes()), |
||||
JsStr::latin1("every".as_bytes()), |
||||
JsStr::latin1("fill".as_bytes()), |
||||
JsStr::latin1("filter".as_bytes()), |
||||
JsStr::latin1("find".as_bytes()), |
||||
JsStr::latin1("findIndex".as_bytes()), |
||||
JsStr::latin1("findLast".as_bytes()), |
||||
JsStr::latin1("findLastIndex".as_bytes()), |
||||
JsStr::latin1("flat".as_bytes()), |
||||
JsStr::latin1("flatMap".as_bytes()), |
||||
JsStr::latin1("forEach".as_bytes()), |
||||
JsStr::latin1("includes".as_bytes()), |
||||
JsStr::latin1("indexOf".as_bytes()), |
||||
JsStr::latin1("join".as_bytes()), |
||||
JsStr::latin1("map".as_bytes()), |
||||
JsStr::latin1("next".as_bytes()), |
||||
JsStr::latin1("reduce".as_bytes()), |
||||
JsStr::latin1("reduceRight".as_bytes()), |
||||
JsStr::latin1("reverse".as_bytes()), |
||||
JsStr::latin1("shift".as_bytes()), |
||||
JsStr::latin1("slice".as_bytes()), |
||||
JsStr::latin1("splice".as_bytes()), |
||||
JsStr::latin1("some".as_bytes()), |
||||
JsStr::latin1("sort".as_bytes()), |
||||
JsStr::latin1("unshift".as_bytes()), |
||||
JsStr::latin1("push".as_bytes()), |
||||
JsStr::latin1("pop".as_bytes()), |
||||
JsStr::latin1("groupBy".as_bytes()), |
||||
JsStr::latin1("toReversed".as_bytes()), |
||||
JsStr::latin1("toSorted".as_bytes()), |
||||
JsStr::latin1("toSpliced".as_bytes()), |
||||
JsStr::latin1("with".as_bytes()), |
||||
// String object
|
||||
JsStr::latin1("charAt".as_bytes()), |
||||
JsStr::latin1("charCodeAt".as_bytes()), |
||||
JsStr::latin1("codePointAt".as_bytes()), |
||||
JsStr::latin1("concat".as_bytes()), |
||||
JsStr::latin1("endsWith".as_bytes()), |
||||
JsStr::latin1("fromCharCode".as_bytes()), |
||||
JsStr::latin1("fromCodePoint".as_bytes()), |
||||
JsStr::latin1("lastIndexOf".as_bytes()), |
||||
JsStr::latin1("match".as_bytes()), |
||||
JsStr::latin1("matchAll".as_bytes()), |
||||
JsStr::latin1("normalize".as_bytes()), |
||||
JsStr::latin1("padEnd".as_bytes()), |
||||
JsStr::latin1("padStart".as_bytes()), |
||||
JsStr::latin1("raw".as_bytes()), |
||||
JsStr::latin1("repeat".as_bytes()), |
||||
JsStr::latin1("replace".as_bytes()), |
||||
JsStr::latin1("replaceAll".as_bytes()), |
||||
JsStr::latin1("search".as_bytes()), |
||||
JsStr::latin1("split".as_bytes()), |
||||
JsStr::latin1("startsWith".as_bytes()), |
||||
JsStr::latin1("substr".as_bytes()), |
||||
JsStr::latin1("substring".as_bytes()), |
||||
JsStr::latin1("toLocaleString".as_bytes()), |
||||
JsStr::latin1("toLowerCase".as_bytes()), |
||||
JsStr::latin1("toUpperCase".as_bytes()), |
||||
JsStr::latin1("trim".as_bytes()), |
||||
JsStr::latin1("trimEnd".as_bytes()), |
||||
JsStr::latin1("trimStart".as_bytes()), |
||||
JsStr::latin1("isWellFormed".as_bytes()), |
||||
JsStr::latin1("localeCompare".as_bytes()), |
||||
JsStr::latin1("toWellFormed".as_bytes()), |
||||
JsStr::latin1("toLocaleLowerCase".as_bytes()), |
||||
JsStr::latin1("toLocaleUpperCase".as_bytes()), |
||||
JsStr::latin1("trimLeft".as_bytes()), |
||||
JsStr::latin1("trimRight".as_bytes()), |
||||
JsStr::latin1("anchor".as_bytes()), |
||||
JsStr::latin1("big".as_bytes()), |
||||
JsStr::latin1("blink".as_bytes()), |
||||
JsStr::latin1("bold".as_bytes()), |
||||
JsStr::latin1("fixed".as_bytes()), |
||||
JsStr::latin1("fontcolor".as_bytes()), |
||||
JsStr::latin1("fontsize".as_bytes()), |
||||
JsStr::latin1("italics".as_bytes()), |
||||
JsStr::latin1("link".as_bytes()), |
||||
JsStr::latin1("small".as_bytes()), |
||||
JsStr::latin1("strike".as_bytes()), |
||||
JsStr::latin1("sub".as_bytes()), |
||||
JsStr::latin1("sup".as_bytes()), |
||||
// Number object
|
||||
JsStr::latin1("Infinity".as_bytes()), |
||||
JsStr::latin1("NaN".as_bytes()), |
||||
JsStr::latin1("EPSILON".as_bytes()), |
||||
JsStr::latin1("MAX_SAFE_INTEGER".as_bytes()), |
||||
JsStr::latin1("MIN_SAFE_INTEGER".as_bytes()), |
||||
JsStr::latin1("MAX_VALUE".as_bytes()), |
||||
JsStr::latin1("MIN_VALUE".as_bytes()), |
||||
JsStr::latin1("NEGATIVE_INFINITY".as_bytes()), |
||||
JsStr::latin1("POSITIVE_INFINITY".as_bytes()), |
||||
JsStr::latin1("isSafeInteger".as_bytes()), |
||||
JsStr::latin1("isInteger".as_bytes()), |
||||
JsStr::latin1("toExponential".as_bytes()), |
||||
JsStr::latin1("toFixed".as_bytes()), |
||||
JsStr::latin1("toPrecision".as_bytes()), |
||||
// BigInt object
|
||||
JsStr::latin1("asIntN".as_bytes()), |
||||
JsStr::latin1("asUintN".as_bytes()), |
||||
// RegExp object
|
||||
JsStr::latin1("exec".as_bytes()), |
||||
JsStr::latin1("test".as_bytes()), |
||||
JsStr::latin1("compile".as_bytes()), |
||||
JsStr::latin1("flags".as_bytes()), |
||||
JsStr::latin1("index".as_bytes()), |
||||
JsStr::latin1("lastIndex".as_bytes()), |
||||
JsStr::latin1("hasIndices".as_bytes()), |
||||
JsStr::latin1("ignoreCase".as_bytes()), |
||||
JsStr::latin1("multiline".as_bytes()), |
||||
JsStr::latin1("dotAll".as_bytes()), |
||||
JsStr::latin1("unicode".as_bytes()), |
||||
JsStr::latin1("sticky".as_bytes()), |
||||
JsStr::latin1("source".as_bytes()), |
||||
JsStr::latin1("get hasIndices".as_bytes()), |
||||
JsStr::latin1("get global".as_bytes()), |
||||
JsStr::latin1("get ignoreCase".as_bytes()), |
||||
JsStr::latin1("get multiline".as_bytes()), |
||||
JsStr::latin1("get dotAll".as_bytes()), |
||||
JsStr::latin1("get unicode".as_bytes()), |
||||
JsStr::latin1("get sticky".as_bytes()), |
||||
JsStr::latin1("get flags".as_bytes()), |
||||
JsStr::latin1("get source".as_bytes()), |
||||
// Symbol object
|
||||
JsStr::latin1("for".as_bytes()), |
||||
JsStr::latin1("keyFor".as_bytes()), |
||||
JsStr::latin1("description".as_bytes()), |
||||
JsStr::latin1("asyncIterator".as_bytes()), |
||||
JsStr::latin1("hasInstance".as_bytes()), |
||||
JsStr::latin1("species".as_bytes()), |
||||
JsStr::latin1("unscopables".as_bytes()), |
||||
JsStr::latin1("iterator".as_bytes()), |
||||
JsStr::latin1("toStringTag".as_bytes()), |
||||
JsStr::latin1("toPrimitive".as_bytes()), |
||||
JsStr::latin1("isConcatSpreadable".as_bytes()), |
||||
JsStr::latin1("get description".as_bytes()), |
||||
// Map object
|
||||
JsStr::latin1("clear".as_bytes()), |
||||
JsStr::latin1("delete".as_bytes()), |
||||
JsStr::latin1("has".as_bytes()), |
||||
JsStr::latin1("size".as_bytes()), |
||||
// Set object
|
||||
JsStr::latin1("add".as_bytes()), |
||||
// Reflect object
|
||||
// Proxy object
|
||||
JsStr::latin1("revocable".as_bytes()), |
||||
// Error objects
|
||||
JsStr::latin1("message".as_bytes()), |
||||
// Date object
|
||||
JsStr::latin1("toJSON".as_bytes()), |
||||
JsStr::latin1("getDate".as_bytes()), |
||||
JsStr::latin1("getDay".as_bytes()), |
||||
JsStr::latin1("getFullYear".as_bytes()), |
||||
JsStr::latin1("getHours".as_bytes()), |
||||
JsStr::latin1("getMilliseconds".as_bytes()), |
||||
JsStr::latin1("getMinutes".as_bytes()), |
||||
JsStr::latin1("getMonth".as_bytes()), |
||||
JsStr::latin1("getSeconds".as_bytes()), |
||||
JsStr::latin1("getTime".as_bytes()), |
||||
JsStr::latin1("getYear".as_bytes()), |
||||
JsStr::latin1("getUTCDate".as_bytes()), |
||||
JsStr::latin1("getUTCDay".as_bytes()), |
||||
JsStr::latin1("getUTCFullYear".as_bytes()), |
||||
JsStr::latin1("getUTCHours".as_bytes()), |
||||
JsStr::latin1("getUTCMinutes".as_bytes()), |
||||
JsStr::latin1("getUTCMonth".as_bytes()), |
||||
JsStr::latin1("getUTCSeconds".as_bytes()), |
||||
JsStr::latin1("setDate".as_bytes()), |
||||
JsStr::latin1("setFullYear".as_bytes()), |
||||
JsStr::latin1("setHours".as_bytes()), |
||||
JsStr::latin1("setMilliseconds".as_bytes()), |
||||
JsStr::latin1("setMinutes".as_bytes()), |
||||
JsStr::latin1("setMonth".as_bytes()), |
||||
JsStr::latin1("setSeconds".as_bytes()), |
||||
JsStr::latin1("setYear".as_bytes()), |
||||
JsStr::latin1("setTime".as_bytes()), |
||||
JsStr::latin1("setUTCDate".as_bytes()), |
||||
JsStr::latin1("setUTCFullYear".as_bytes()), |
||||
JsStr::latin1("setUTCHours".as_bytes()), |
||||
JsStr::latin1("setUTCMinutes".as_bytes()), |
||||
JsStr::latin1("setUTCMonth".as_bytes()), |
||||
JsStr::latin1("setUTCSeconds".as_bytes()), |
||||
JsStr::latin1("toDateString".as_bytes()), |
||||
JsStr::latin1("toGMTString".as_bytes()), |
||||
JsStr::latin1("toISOString".as_bytes()), |
||||
JsStr::latin1("toTimeString".as_bytes()), |
||||
JsStr::latin1("toUTCString".as_bytes()), |
||||
JsStr::latin1("now".as_bytes()), |
||||
JsStr::latin1("UTC".as_bytes()), |
||||
JsStr::latin1("getTimezoneOffset".as_bytes()), |
||||
JsStr::latin1("getUTCMilliseconds".as_bytes()), |
||||
JsStr::latin1("setUTCMilliseconds".as_bytes()), |
||||
JsStr::latin1("toLocaleDateString".as_bytes()), |
||||
JsStr::latin1("toLocaleTimeString".as_bytes()), |
||||
// JSON object
|
||||
JsStr::latin1("parse".as_bytes()), |
||||
JsStr::latin1("stringify".as_bytes()), |
||||
// Promise object
|
||||
JsStr::latin1("promise".as_bytes()), |
||||
JsStr::latin1("resolve".as_bytes()), |
||||
JsStr::latin1("reject".as_bytes()), |
||||
JsStr::latin1("all".as_bytes()), |
||||
JsStr::latin1("allSettled".as_bytes()), |
||||
JsStr::latin1("any".as_bytes()), |
||||
JsStr::latin1("race".as_bytes()), |
||||
JsStr::latin1("then".as_bytes()), |
||||
JsStr::latin1("catch".as_bytes()), |
||||
JsStr::latin1("finally".as_bytes()), |
||||
JsStr::latin1("withResolvers".as_bytes()), |
||||
// Iterator object
|
||||
JsStr::latin1("Array Iterator".as_bytes()), |
||||
JsStr::latin1("Set Iterator".as_bytes()), |
||||
JsStr::latin1("String Iterator".as_bytes()), |
||||
JsStr::latin1("Map Iterator".as_bytes()), |
||||
JsStr::latin1("For In Iterator".as_bytes()), |
||||
JsStr::latin1("RegExp String Iterator".as_bytes()), |
||||
// Iterator result object
|
||||
JsStr::latin1("done".as_bytes()), |
||||
// Math object
|
||||
JsStr::latin1("LN10".as_bytes()), |
||||
JsStr::latin1("LN2".as_bytes()), |
||||
JsStr::latin1("LOG10E".as_bytes()), |
||||
JsStr::latin1("LOG2E".as_bytes()), |
||||
JsStr::latin1("PI".as_bytes()), |
||||
JsStr::latin1("SQRT1_2".as_bytes()), |
||||
JsStr::latin1("SQRT2".as_bytes()), |
||||
JsStr::latin1("abs".as_bytes()), |
||||
JsStr::latin1("acos".as_bytes()), |
||||
JsStr::latin1("acosh".as_bytes()), |
||||
JsStr::latin1("asin".as_bytes()), |
||||
JsStr::latin1("asinh".as_bytes()), |
||||
JsStr::latin1("atan".as_bytes()), |
||||
JsStr::latin1("atanh".as_bytes()), |
||||
JsStr::latin1("atan2".as_bytes()), |
||||
JsStr::latin1("cbrt".as_bytes()), |
||||
JsStr::latin1("ceil".as_bytes()), |
||||
JsStr::latin1("clz32".as_bytes()), |
||||
JsStr::latin1("cos".as_bytes()), |
||||
JsStr::latin1("cosh".as_bytes()), |
||||
JsStr::latin1("exp".as_bytes()), |
||||
JsStr::latin1("expm1".as_bytes()), |
||||
JsStr::latin1("floor".as_bytes()), |
||||
JsStr::latin1("fround".as_bytes()), |
||||
JsStr::latin1("hypot".as_bytes()), |
||||
JsStr::latin1("imul".as_bytes()), |
||||
JsStr::latin1("log".as_bytes()), |
||||
JsStr::latin1("log1p".as_bytes()), |
||||
JsStr::latin1("log10".as_bytes()), |
||||
JsStr::latin1("log2".as_bytes()), |
||||
JsStr::latin1("max".as_bytes()), |
||||
JsStr::latin1("min".as_bytes()), |
||||
JsStr::latin1("pow".as_bytes()), |
||||
JsStr::latin1("random".as_bytes()), |
||||
JsStr::latin1("round".as_bytes()), |
||||
JsStr::latin1("sign".as_bytes()), |
||||
JsStr::latin1("sin".as_bytes()), |
||||
JsStr::latin1("sinh".as_bytes()), |
||||
JsStr::latin1("sqrt".as_bytes()), |
||||
JsStr::latin1("tan".as_bytes()), |
||||
JsStr::latin1("tanh".as_bytes()), |
||||
JsStr::latin1("trunc".as_bytes()), |
||||
// TypedArray object
|
||||
JsStr::latin1("BYTES_PER_ELEMENT".as_bytes()), |
||||
JsStr::latin1("buffer".as_bytes()), |
||||
JsStr::latin1("byteLength".as_bytes()), |
||||
JsStr::latin1("byteOffset".as_bytes()), |
||||
JsStr::latin1("isView".as_bytes()), |
||||
JsStr::latin1("subarray".as_bytes()), |
||||
JsStr::latin1("get byteLength".as_bytes()), |
||||
JsStr::latin1("get buffer".as_bytes()), |
||||
JsStr::latin1("get byteOffset".as_bytes()), |
||||
JsStr::latin1("get size".as_bytes()), |
||||
JsStr::latin1("get length".as_bytes()), |
||||
// DataView object
|
||||
JsStr::latin1("getBigInt64".as_bytes()), |
||||
JsStr::latin1("getBigUint64".as_bytes()), |
||||
JsStr::latin1("getFloat32".as_bytes()), |
||||
JsStr::latin1("getFloat64".as_bytes()), |
||||
JsStr::latin1("getInt8".as_bytes()), |
||||
JsStr::latin1("getInt16".as_bytes()), |
||||
JsStr::latin1("getInt32".as_bytes()), |
||||
JsStr::latin1("getUint8".as_bytes()), |
||||
JsStr::latin1("getUint16".as_bytes()), |
||||
JsStr::latin1("getUint32".as_bytes()), |
||||
JsStr::latin1("setBigInt64".as_bytes()), |
||||
JsStr::latin1("setBigUint64".as_bytes()), |
||||
JsStr::latin1("setFloat32".as_bytes()), |
||||
JsStr::latin1("setFloat64".as_bytes()), |
||||
JsStr::latin1("setInt8".as_bytes()), |
||||
JsStr::latin1("setInt16".as_bytes()), |
||||
JsStr::latin1("setInt32".as_bytes()), |
||||
JsStr::latin1("setUint8".as_bytes()), |
||||
JsStr::latin1("setUint16".as_bytes()), |
||||
JsStr::latin1("setUint32".as_bytes()), |
||||
// WeakRef object
|
||||
JsStr::latin1("deref".as_bytes()), |
||||
// Atomic object
|
||||
JsStr::latin1("and".as_bytes()), |
||||
JsStr::latin1("compareExchange".as_bytes()), |
||||
JsStr::latin1("exchange".as_bytes()), |
||||
JsStr::latin1("isLockFree".as_bytes()), |
||||
JsStr::latin1("load".as_bytes()), |
||||
JsStr::latin1("or".as_bytes()), |
||||
JsStr::latin1("store".as_bytes()), |
||||
JsStr::latin1("wait".as_bytes()), |
||||
JsStr::latin1("notify".as_bytes()), |
||||
JsStr::latin1("xor".as_bytes()), |
||||
// Intl object
|
||||
JsStr::latin1("getCanonicalLocales".as_bytes()), |
||||
JsStr::latin1("get compare".as_bytes()), |
||||
JsStr::latin1("supportedLocalesOf".as_bytes()), |
||||
JsStr::latin1("Intl.Collator".as_bytes()), |
||||
JsStr::latin1("compare".as_bytes()), |
||||
JsStr::latin1("resolvedOptions".as_bytes()), |
||||
JsStr::latin1("Intl.ListFormat".as_bytes()), |
||||
JsStr::latin1("format".as_bytes()), |
||||
JsStr::latin1("formatToParts".as_bytes()), |
||||
JsStr::latin1("get baseName".as_bytes()), |
||||
JsStr::latin1("get calendar".as_bytes()), |
||||
JsStr::latin1("get caseFirst".as_bytes()), |
||||
JsStr::latin1("get collation".as_bytes()), |
||||
JsStr::latin1("get hourCycle".as_bytes()), |
||||
JsStr::latin1("get numeric".as_bytes()), |
||||
JsStr::latin1("get numberingSystem".as_bytes()), |
||||
JsStr::latin1("get language".as_bytes()), |
||||
JsStr::latin1("get script".as_bytes()), |
||||
JsStr::latin1("get region".as_bytes()), |
||||
JsStr::latin1("Intl.Locale".as_bytes()), |
||||
JsStr::latin1("maximize".as_bytes()), |
||||
JsStr::latin1("minimize".as_bytes()), |
||||
JsStr::latin1("baseName".as_bytes()), |
||||
JsStr::latin1("calendar".as_bytes()), |
||||
JsStr::latin1("caseFirst".as_bytes()), |
||||
JsStr::latin1("collation".as_bytes()), |
||||
JsStr::latin1("hourCycle".as_bytes()), |
||||
JsStr::latin1("numeric".as_bytes()), |
||||
JsStr::latin1("numberingSystem".as_bytes()), |
||||
JsStr::latin1("language".as_bytes()), |
||||
JsStr::latin1("script".as_bytes()), |
||||
JsStr::latin1("region".as_bytes()), |
||||
JsStr::latin1("Intl.Segmenter".as_bytes()), |
||||
JsStr::latin1("segment".as_bytes()), |
||||
JsStr::latin1("containing".as_bytes()), |
||||
JsStr::latin1("Segmenter String Iterator".as_bytes()), |
||||
JsStr::latin1("Intl.PluralRules".as_bytes()), |
||||
JsStr::latin1("select".as_bytes()), |
||||
// Temporal object
|
||||
JsStr::latin1("get Id".as_bytes()), |
||||
JsStr::latin1("getOffsetNanosecondsFor".as_bytes()), |
||||
JsStr::latin1("getOffsetStringFor".as_bytes()), |
||||
JsStr::latin1("getPlainDateTimeFor".as_bytes()), |
||||
JsStr::latin1("getInstantFor".as_bytes()), |
||||
JsStr::latin1("getPossibleInstantFor".as_bytes()), |
||||
JsStr::latin1("getNextTransition".as_bytes()), |
||||
JsStr::latin1("getPreviousTransition".as_bytes()), |
||||
JsStr::latin1("id".as_bytes()), |
||||
JsStr::latin1("Now".as_bytes()), |
||||
JsStr::latin1("Calendar".as_bytes()), |
||||
JsStr::latin1("Duration".as_bytes()), |
||||
JsStr::latin1("Instant".as_bytes()), |
||||
JsStr::latin1("PlainDate".as_bytes()), |
||||
JsStr::latin1("PlainDateTime".as_bytes()), |
||||
JsStr::latin1("PlainMonthDay".as_bytes()), |
||||
JsStr::latin1("PlainTime".as_bytes()), |
||||
JsStr::latin1("PlainYearMonth".as_bytes()), |
||||
JsStr::latin1("TimeZone".as_bytes()), |
||||
JsStr::latin1("ZonedDateTime".as_bytes()), |
||||
JsStr::latin1("timeZoneId".as_bytes()), |
||||
JsStr::latin1("instant".as_bytes()), |
||||
JsStr::latin1("plainDateTime".as_bytes()), |
||||
JsStr::latin1("plainDateTimeISO".as_bytes()), |
||||
JsStr::latin1("zonedDateTime".as_bytes()), |
||||
JsStr::latin1("zonedDateTimeISO".as_bytes()), |
||||
JsStr::latin1("plainDate".as_bytes()), |
||||
JsStr::latin1("plainDateISO".as_bytes()), |
||||
JsStr::latin1("get epochSeconds".as_bytes()), |
||||
JsStr::latin1("get epochMilliseconds".as_bytes()), |
||||
JsStr::latin1("get epochMicroseconds".as_bytes()), |
||||
JsStr::latin1("get epochNanoseconds".as_bytes()), |
||||
JsStr::latin1("epochSeconds".as_bytes()), |
||||
JsStr::latin1("epochMilliseconds".as_bytes()), |
||||
JsStr::latin1("epochMicroseconds".as_bytes()), |
||||
JsStr::latin1("epochNanoseconds".as_bytes()), |
||||
JsStr::latin1("subtract".as_bytes()), |
||||
JsStr::latin1("until".as_bytes()), |
||||
JsStr::latin1("since".as_bytes()), |
||||
JsStr::latin1("equals".as_bytes()), |
||||
JsStr::latin1("toZonedDateTime".as_bytes()), |
||||
JsStr::latin1("toZonedDateTimeISO".as_bytes()), |
||||
JsStr::latin1("get Years".as_bytes()), |
||||
JsStr::latin1("get Months".as_bytes()), |
||||
JsStr::latin1("get Weeks".as_bytes()), |
||||
JsStr::latin1("get Days".as_bytes()), |
||||
JsStr::latin1("get Hours".as_bytes()), |
||||
JsStr::latin1("get Minutes".as_bytes()), |
||||
JsStr::latin1("get Seconds".as_bytes()), |
||||
JsStr::latin1("get Milliseconds".as_bytes()), |
||||
JsStr::latin1("get Microseconds".as_bytes()), |
||||
JsStr::latin1("get Nanoseconds".as_bytes()), |
||||
JsStr::latin1("get Sign".as_bytes()), |
||||
JsStr::latin1("get blank".as_bytes()), |
||||
JsStr::latin1("years".as_bytes()), |
||||
JsStr::latin1("months".as_bytes()), |
||||
JsStr::latin1("weeks".as_bytes()), |
||||
JsStr::latin1("days".as_bytes()), |
||||
JsStr::latin1("hours".as_bytes()), |
||||
JsStr::latin1("minutes".as_bytes()), |
||||
JsStr::latin1("seconds".as_bytes()), |
||||
JsStr::latin1("milliseconds".as_bytes()), |
||||
JsStr::latin1("microseconds".as_bytes()), |
||||
JsStr::latin1("nanoseconds".as_bytes()), |
||||
JsStr::latin1("blank".as_bytes()), |
||||
JsStr::latin1("negated".as_bytes()), |
||||
JsStr::latin1("total".as_bytes()), |
||||
JsStr::latin1("get calendarId".as_bytes()), |
||||
JsStr::latin1("get year".as_bytes()), |
||||
JsStr::latin1("get month".as_bytes()), |
||||
JsStr::latin1("get monthCode".as_bytes()), |
||||
JsStr::latin1("get day".as_bytes()), |
||||
JsStr::latin1("get dayOfWeek".as_bytes()), |
||||
JsStr::latin1("get dayOfYear".as_bytes()), |
||||
JsStr::latin1("get weekOfYear".as_bytes()), |
||||
JsStr::latin1("get yearOfWeek".as_bytes()), |
||||
JsStr::latin1("get daysInWeek".as_bytes()), |
||||
JsStr::latin1("get daysInMonth".as_bytes()), |
||||
JsStr::latin1("get daysInYear".as_bytes()), |
||||
JsStr::latin1("get monthsInYear".as_bytes()), |
||||
JsStr::latin1("get inLeapYear".as_bytes()), |
||||
JsStr::latin1("calendarId".as_bytes()), |
||||
JsStr::latin1("year".as_bytes()), |
||||
JsStr::latin1("month".as_bytes()), |
||||
JsStr::latin1("monthCode".as_bytes()), |
||||
JsStr::latin1("day".as_bytes()), |
||||
JsStr::latin1("dayOfWeek".as_bytes()), |
||||
JsStr::latin1("dayOfYear".as_bytes()), |
||||
JsStr::latin1("weekOfYear".as_bytes()), |
||||
JsStr::latin1("yearOfWeek".as_bytes()), |
||||
JsStr::latin1("daysInWeek".as_bytes()), |
||||
JsStr::latin1("daysInMonth".as_bytes()), |
||||
JsStr::latin1("daysInYear".as_bytes()), |
||||
JsStr::latin1("monthsInYear".as_bytes()), |
||||
JsStr::latin1("inLeapYear".as_bytes()), |
||||
JsStr::latin1("toPlainYearMonth".as_bytes()), |
||||
JsStr::latin1("toPlainMonthDay".as_bytes()), |
||||
JsStr::latin1("getISOFields".as_bytes()), |
||||
JsStr::latin1("getCalendar".as_bytes()), |
||||
JsStr::latin1("withCalendar".as_bytes()), |
||||
JsStr::latin1("dateFromFields".as_bytes()), |
||||
JsStr::latin1("yearMonthFromFields".as_bytes()), |
||||
JsStr::latin1("monthDayFromFields".as_bytes()), |
||||
JsStr::latin1("dateAdd".as_bytes()), |
||||
JsStr::latin1("dateUntil".as_bytes()), |
||||
JsStr::latin1("era".as_bytes()), |
||||
JsStr::latin1("eraYear".as_bytes()), |
||||
JsStr::latin1("fields".as_bytes()), |
||||
JsStr::latin1("mergeFields".as_bytes()), |
||||
// Console object
|
||||
JsStr::latin1("console".as_bytes()), |
||||
JsStr::latin1("assert".as_bytes()), |
||||
JsStr::latin1("debug".as_bytes()), |
||||
JsStr::latin1("error".as_bytes()), |
||||
JsStr::latin1("info".as_bytes()), |
||||
JsStr::latin1("trace".as_bytes()), |
||||
JsStr::latin1("warn".as_bytes()), |
||||
JsStr::latin1("exception".as_bytes()), |
||||
JsStr::latin1("count".as_bytes()), |
||||
JsStr::latin1("countReset".as_bytes()), |
||||
JsStr::latin1("group".as_bytes()), |
||||
JsStr::latin1("groupCollapsed".as_bytes()), |
||||
JsStr::latin1("groupEnd".as_bytes()), |
||||
JsStr::latin1("time".as_bytes()), |
||||
JsStr::latin1("timeLog".as_bytes()), |
||||
JsStr::latin1("timeEnd".as_bytes()), |
||||
JsStr::latin1("dir".as_bytes()), |
||||
JsStr::latin1("dirxml".as_bytes()), |
||||
// Minified name
|
||||
JsStr::latin1("a".as_bytes()), |
||||
JsStr::latin1("c".as_bytes()), |
||||
JsStr::latin1("d".as_bytes()), |
||||
JsStr::latin1("e".as_bytes()), |
||||
JsStr::latin1("f".as_bytes()), |
||||
JsStr::latin1("g".as_bytes()), |
||||
JsStr::latin1("h".as_bytes()), |
||||
JsStr::latin1("i".as_bytes()), |
||||
JsStr::latin1("j".as_bytes()), |
||||
JsStr::latin1("k".as_bytes()), |
||||
JsStr::latin1("l".as_bytes()), |
||||
JsStr::latin1("m".as_bytes()), |
||||
JsStr::latin1("n".as_bytes()), |
||||
JsStr::latin1("o".as_bytes()), |
||||
JsStr::latin1("p".as_bytes()), |
||||
JsStr::latin1("q".as_bytes()), |
||||
JsStr::latin1("r".as_bytes()), |
||||
JsStr::latin1("s".as_bytes()), |
||||
JsStr::latin1("t".as_bytes()), |
||||
JsStr::latin1("u".as_bytes()), |
||||
JsStr::latin1("v".as_bytes()), |
||||
JsStr::latin1("w".as_bytes()), |
||||
JsStr::latin1("x".as_bytes()), |
||||
JsStr::latin1("y".as_bytes()), |
||||
JsStr::latin1("z".as_bytes()), |
||||
JsStr::latin1("A".as_bytes()), |
||||
JsStr::latin1("C".as_bytes()), |
||||
JsStr::latin1("D".as_bytes()), |
||||
JsStr::latin1("E".as_bytes()), |
||||
JsStr::latin1("F".as_bytes()), |
||||
JsStr::latin1("G".as_bytes()), |
||||
JsStr::latin1("H".as_bytes()), |
||||
JsStr::latin1("I".as_bytes()), |
||||
JsStr::latin1("J".as_bytes()), |
||||
JsStr::latin1("K".as_bytes()), |
||||
JsStr::latin1("L".as_bytes()), |
||||
JsStr::latin1("M".as_bytes()), |
||||
JsStr::latin1("N".as_bytes()), |
||||
JsStr::latin1("O".as_bytes()), |
||||
JsStr::latin1("P".as_bytes()), |
||||
JsStr::latin1("Q".as_bytes()), |
||||
JsStr::latin1("R".as_bytes()), |
||||
JsStr::latin1("S".as_bytes()), |
||||
JsStr::latin1("T".as_bytes()), |
||||
JsStr::latin1("U".as_bytes()), |
||||
JsStr::latin1("V".as_bytes()), |
||||
JsStr::latin1("W".as_bytes()), |
||||
JsStr::latin1("X".as_bytes()), |
||||
JsStr::latin1("Y".as_bytes()), |
||||
JsStr::latin1("Z".as_bytes()), |
||||
JsStr::latin1("_".as_bytes()), |
||||
JsStr::latin1("$".as_bytes()), |
||||
]; |
@ -0,0 +1,109 @@
|
||||
// Remove when/if https://github.com/rust-lang/rust/issues/95228 stabilizes.
|
||||
// Right now this allows us to use the stable polyfill from the `sptr` crate, which uses
|
||||
// the same names from the unstable functions of the `std::ptr` module.
|
||||
#![allow(unstable_name_collisions)] |
||||
|
||||
use sptr::Strict; |
||||
use std::ptr::NonNull; |
||||
|
||||
/// A pointer that can be tagged with an `usize`.
|
||||
///
|
||||
/// Only pointers with a minimum alignment of 2-bytes are valid, and the tag must have its most
|
||||
/// significant bit (MSB) unset. In other words, the tag must fit inside `usize::BITS - 1` bits.
|
||||
///
|
||||
/// # Representation
|
||||
///
|
||||
/// If the least significant bit (LSB) of the internal [`NonNull`] is set (1), then the pointer
|
||||
/// address represents a tag where the remaining bits store the tag. Otherwise, the whole pointer
|
||||
/// represents the pointer itself.
|
||||
///
|
||||
/// It uses [`NonNull`], which guarantees that [`Tagged`] can use the "null pointer optimization"
|
||||
/// to optimize the size of [`Option<Tagged>`].
|
||||
///
|
||||
/// # Provenance
|
||||
///
|
||||
/// This struct stores a [`NonNull<T>`] instead of a [`NonZeroUsize`][std::num::NonZeroUsize]
|
||||
/// in order to preserve the provenance of our valid heap pointers.
|
||||
/// On the other hand, all index values are just casted to invalid pointers, because we don't need to
|
||||
/// preserve the provenance of [`usize`] indices.
|
||||
///
|
||||
/// [tagged_wp]: https://en.wikipedia.org/wiki/Tagged_pointer
|
||||
#[derive(Debug)] |
||||
pub(crate) struct Tagged<T>(NonNull<T>); |
||||
|
||||
impl<T> Clone for Tagged<T> { |
||||
fn clone(&self) -> Self { |
||||
*self |
||||
} |
||||
} |
||||
|
||||
impl<T> Copy for Tagged<T> {} |
||||
|
||||
impl<T> Tagged<T> { |
||||
/// Creates a new, tagged `Tagged` pointer from an integer.
|
||||
///
|
||||
/// # Requirements
|
||||
///
|
||||
/// - `T` must have an alignment of at least 2.
|
||||
/// - `tag` must fit inside `usize::BITS - 1` bits
|
||||
pub(crate) const fn from_tag(tag: usize) -> Self { |
||||
debug_assert!(std::mem::align_of::<T>() >= 2); |
||||
let addr = (tag << 1) | 1; |
||||
// SAFETY: `addr` is never zero, since we always set its LSB to 1
|
||||
unsafe { Self(NonNull::new_unchecked(sptr::invalid_mut(addr))) } |
||||
} |
||||
|
||||
/// Creates a new `Tagged` pointer from a raw pointer.
|
||||
///
|
||||
/// # Requirements
|
||||
///
|
||||
/// - `T` must have an alignment of at least 2.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `T` must be non null.
|
||||
pub(crate) const unsafe fn from_ptr(ptr: *mut T) -> Self { |
||||
debug_assert!(std::mem::align_of::<T>() >= 2); |
||||
// SAFETY: the caller must ensure the invariants hold.
|
||||
unsafe { Self(NonNull::new_unchecked(ptr)) } |
||||
} |
||||
|
||||
/// Creates a new `Tagged` pointer from a `NonNull` pointer.
|
||||
///
|
||||
/// # Requirements
|
||||
///
|
||||
/// - `T` must have an alignment of at least 2.
|
||||
pub(crate) const fn from_non_null(ptr: NonNull<T>) -> Self { |
||||
debug_assert!(std::mem::align_of::<T>() >= 2); |
||||
Self(ptr) |
||||
} |
||||
|
||||
/// Unwraps the `Tagged` pointer.
|
||||
pub(crate) fn unwrap(self) -> UnwrappedTagged<T> { |
||||
let addr = self.0.as_ptr().addr(); |
||||
if addr & 1 == 0 { |
||||
UnwrappedTagged::Ptr(self.0) |
||||
} else { |
||||
UnwrappedTagged::Tag(addr >> 1) |
||||
} |
||||
} |
||||
|
||||
/// Gets the address of the inner pointer.
|
||||
#[allow(unused)] |
||||
pub(crate) fn addr(self) -> usize { |
||||
self.0.as_ptr().addr() |
||||
} |
||||
|
||||
/// Returns `true` if `self ` is a tagged pointer.
|
||||
#[allow(unused)] |
||||
pub(crate) fn is_tagged(self) -> bool { |
||||
self.0.as_ptr().addr() & 1 > 0 |
||||
} |
||||
} |
||||
|
||||
/// The unwrapped value of a [`Tagged`] pointer.
|
||||
#[derive(Debug, Clone, Copy)] |
||||
pub(crate) enum UnwrappedTagged<T> { |
||||
Ptr(NonNull<T>), |
||||
Tag(usize), |
||||
} |
@ -0,0 +1,166 @@
|
||||
#![allow(clippy::redundant_clone)] |
||||
|
||||
use std::hash::{BuildHasher, BuildHasherDefault, Hash}; |
||||
|
||||
use crate::{JsStr, JsString, StaticJsStrings}; |
||||
|
||||
use boa_macros::utf16; |
||||
use rustc_hash::FxHasher; |
||||
|
||||
fn hash_value<T: Hash>(value: &T) -> u64 { |
||||
BuildHasherDefault::<FxHasher>::default().hash_one(value) |
||||
} |
||||
|
||||
#[test] |
||||
fn empty() { |
||||
let s = StaticJsStrings::EMPTY_STRING; |
||||
assert_eq!(&s, utf16!("")); |
||||
} |
||||
|
||||
#[test] |
||||
fn refcount() { |
||||
let x = JsString::from("Hello world"); |
||||
assert_eq!(x.refcount(), Some(1)); |
||||
|
||||
{ |
||||
let y = x.clone(); |
||||
assert_eq!(x.refcount(), Some(2)); |
||||
assert_eq!(y.refcount(), Some(2)); |
||||
|
||||
{ |
||||
let z = y.clone(); |
||||
assert_eq!(x.refcount(), Some(3)); |
||||
assert_eq!(y.refcount(), Some(3)); |
||||
assert_eq!(z.refcount(), Some(3)); |
||||
} |
||||
|
||||
assert_eq!(x.refcount(), Some(2)); |
||||
assert_eq!(y.refcount(), Some(2)); |
||||
} |
||||
|
||||
assert_eq!(x.refcount(), Some(1)); |
||||
} |
||||
|
||||
#[test] |
||||
fn static_refcount() { |
||||
let x = StaticJsStrings::EMPTY_STRING; |
||||
assert_eq!(x.refcount(), None); |
||||
|
||||
{ |
||||
let y = x.clone(); |
||||
assert_eq!(x.refcount(), None); |
||||
assert_eq!(y.refcount(), None); |
||||
}; |
||||
|
||||
assert_eq!(x.refcount(), None); |
||||
} |
||||
|
||||
#[test] |
||||
fn ptr_eq() { |
||||
let x = JsString::from("Hello"); |
||||
let y = x.clone(); |
||||
|
||||
assert!(!x.ptr.is_tagged()); |
||||
|
||||
assert_eq!(x.ptr.addr(), y.ptr.addr()); |
||||
|
||||
let z = JsString::from("Hello"); |
||||
assert_ne!(x.ptr.addr(), z.ptr.addr()); |
||||
assert_ne!(y.ptr.addr(), z.ptr.addr()); |
||||
} |
||||
|
||||
#[test] |
||||
fn static_ptr_eq() { |
||||
let x = StaticJsStrings::EMPTY_STRING; |
||||
let y = x.clone(); |
||||
|
||||
assert!(x.ptr.is_tagged()); |
||||
|
||||
assert_eq!(x.ptr.addr(), y.ptr.addr()); |
||||
|
||||
let z = StaticJsStrings::EMPTY_STRING; |
||||
assert_eq!(x.ptr.addr(), z.ptr.addr()); |
||||
assert_eq!(y.ptr.addr(), z.ptr.addr()); |
||||
} |
||||
|
||||
#[test] |
||||
fn as_str() { |
||||
const HELLO: &[u16] = utf16!("Hello"); |
||||
let x = JsString::from(HELLO); |
||||
|
||||
assert_eq!(&x, HELLO); |
||||
} |
||||
|
||||
#[test] |
||||
fn hash() { |
||||
const HELLOWORLD: JsStr<'_> = JsStr::latin1("Hello World!".as_bytes()); |
||||
let x = JsString::from(HELLOWORLD); |
||||
|
||||
assert_eq!(x.as_str(), HELLOWORLD); |
||||
|
||||
assert!(HELLOWORLD.is_latin1()); |
||||
assert!(x.as_str().is_latin1()); |
||||
|
||||
let s_hash = hash_value(&HELLOWORLD); |
||||
let x_hash = hash_value(&x); |
||||
|
||||
assert_eq!(s_hash, x_hash); |
||||
} |
||||
|
||||
#[test] |
||||
fn concat() { |
||||
const Y: &[u16] = utf16!(", "); |
||||
const W: &[u16] = utf16!("!"); |
||||
|
||||
let x = JsString::from("hello"); |
||||
let z = JsString::from("world"); |
||||
|
||||
let xy = JsString::concat(x.as_str(), JsString::from(Y).as_str()); |
||||
assert_eq!(&xy, utf16!("hello, ")); |
||||
assert_eq!(xy.refcount(), Some(1)); |
||||
|
||||
let xyz = JsString::concat(xy.as_str(), z.as_str()); |
||||
assert_eq!(&xyz, utf16!("hello, world")); |
||||
assert_eq!(xyz.refcount(), Some(1)); |
||||
|
||||
let xyzw = JsString::concat(xyz.as_str(), JsString::from(W).as_str()); |
||||
assert_eq!(&xyzw, utf16!("hello, world!")); |
||||
assert_eq!(xyzw.refcount(), Some(1)); |
||||
} |
||||
|
||||
#[test] |
||||
fn trim_start_non_ascii_to_ascii() { |
||||
let s = "\u{2029}abc"; |
||||
let x = JsString::from(s); |
||||
|
||||
let y = JsString::from(x.trim_start()); |
||||
|
||||
assert_eq!(&y, s.trim_start()); |
||||
} |
||||
|
||||
#[test] |
||||
fn conversion_to_known_static_js_string() { |
||||
const JS_STR_U8: &JsStr<'_> = &JsStr::latin1("length".as_bytes()); |
||||
const JS_STR_U16: &JsStr<'_> = &JsStr::utf16(utf16!("length")); |
||||
|
||||
assert!(JS_STR_U8.is_latin1()); |
||||
assert!(!JS_STR_U16.is_latin1()); |
||||
|
||||
assert_eq!(JS_STR_U8, JS_STR_U8); |
||||
assert_eq!(JS_STR_U16, JS_STR_U16); |
||||
|
||||
assert_eq!(JS_STR_U8, JS_STR_U16); |
||||
assert_eq!(JS_STR_U16, JS_STR_U8); |
||||
|
||||
assert_eq!(hash_value(JS_STR_U8), hash_value(JS_STR_U16)); |
||||
|
||||
let string = StaticJsStrings::get_string(JS_STR_U8); |
||||
|
||||
assert!(string.is_some()); |
||||
assert!(string.unwrap().as_str().is_latin1()); |
||||
|
||||
let string = StaticJsStrings::get_string(JS_STR_U16); |
||||
|
||||
assert!(string.is_some()); |
||||
assert!(string.unwrap().as_str().is_latin1()); |
||||
} |
Loading…
Reference in new issue