|
|
|
@ -26,6 +26,200 @@ use crate::{
|
|
|
|
|
}; |
|
|
|
|
use gc::{Finalize, Trace}; |
|
|
|
|
|
|
|
|
|
/// A structure that contains the JavaScript well known symbols.
|
|
|
|
|
#[derive(Debug, Clone)] |
|
|
|
|
pub struct WellKnownSymbols { |
|
|
|
|
async_iterator: RcSymbol, |
|
|
|
|
has_instance: RcSymbol, |
|
|
|
|
is_concat_spreadable: RcSymbol, |
|
|
|
|
iterator: RcSymbol, |
|
|
|
|
match_: RcSymbol, |
|
|
|
|
match_all: RcSymbol, |
|
|
|
|
replace: RcSymbol, |
|
|
|
|
search: RcSymbol, |
|
|
|
|
species: RcSymbol, |
|
|
|
|
split: RcSymbol, |
|
|
|
|
to_primitive: RcSymbol, |
|
|
|
|
to_string_tag: RcSymbol, |
|
|
|
|
unscopables: RcSymbol, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl WellKnownSymbols { |
|
|
|
|
pub(crate) fn new() -> (Self, u32) { |
|
|
|
|
let mut count = 0; |
|
|
|
|
|
|
|
|
|
let async_iterator = Symbol::new(count, Some("Symbol.asyncIterator".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let has_instance = Symbol::new(count, Some("Symbol.hasInstance".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let is_concat_spreadable = |
|
|
|
|
Symbol::new(count, Some("Symbol.isConcatSpreadable".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let iterator = Symbol::new(count, Some("Symbol.iterator".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let match_ = Symbol::new(count, Some("Symbol.match".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let match_all = Symbol::new(count, Some("Symbol.matchAll".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let replace = Symbol::new(count, Some("Symbol.replace".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let search = Symbol::new(count, Some("Symbol.search".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let species = Symbol::new(count, Some("Symbol.species".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let split = Symbol::new(count, Some("Symbol.split".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let to_primitive = Symbol::new(count, Some("Symbol.toPrimitive".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let to_string_tag = Symbol::new(count, Some("Symbol.toStringTag".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
let unscopables = Symbol::new(count, Some("Symbol.unscopables".into())).into(); |
|
|
|
|
count += 1; |
|
|
|
|
|
|
|
|
|
( |
|
|
|
|
Self { |
|
|
|
|
async_iterator, |
|
|
|
|
has_instance, |
|
|
|
|
is_concat_spreadable, |
|
|
|
|
iterator, |
|
|
|
|
match_, |
|
|
|
|
match_all, |
|
|
|
|
replace, |
|
|
|
|
search, |
|
|
|
|
species, |
|
|
|
|
split, |
|
|
|
|
to_primitive, |
|
|
|
|
to_string_tag, |
|
|
|
|
unscopables, |
|
|
|
|
}, |
|
|
|
|
count, |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.asyncIterator` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A method that returns the default AsyncIterator for an object.
|
|
|
|
|
/// Called by the semantics of the `for-await-of` statement.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn async_iterator_symbol(&self) -> RcSymbol { |
|
|
|
|
self.async_iterator.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.hasInstance` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A method that determines if a `constructor` object
|
|
|
|
|
/// recognizes an object as one of the `constructor`'s instances.
|
|
|
|
|
/// Called by the semantics of the instanceof operator.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn has_instance_symbol(&self) -> RcSymbol { |
|
|
|
|
self.async_iterator.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.isConcatSpreadable` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A Boolean valued property that if `true` indicates that
|
|
|
|
|
/// an object should be flattened to its array elements
|
|
|
|
|
/// by `Array.prototype.concat`.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn is_concat_spreadable_symbol(&self) -> RcSymbol { |
|
|
|
|
self.is_concat_spreadable.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.iterator` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A method that returns the default Iterator for an object.
|
|
|
|
|
/// Called by the semantics of the `for-of` statement.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn iterator_symbol(&self) -> RcSymbol { |
|
|
|
|
self.iterator.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.match` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A regular expression method that matches the regular expression
|
|
|
|
|
/// against a string. Called by the `String.prototype.match` method.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn match_symbol(&self) -> RcSymbol { |
|
|
|
|
self.match_.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.matchAll` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A regular expression method that returns an iterator, that yields
|
|
|
|
|
/// matches of the regular expression against a string.
|
|
|
|
|
/// Called by the `String.prototype.matchAll` method.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn match_all_symbol(&self) -> RcSymbol { |
|
|
|
|
self.match_all.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.replace` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A regular expression method that replaces matched substrings
|
|
|
|
|
/// of a string. Called by the `String.prototype.replace` method.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn replace_symbol(&self) -> RcSymbol { |
|
|
|
|
self.replace.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.search` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A regular expression method that returns the index within a
|
|
|
|
|
/// string that matches the regular expression.
|
|
|
|
|
/// Called by the `String.prototype.search` method.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn search_symbol(&self) -> RcSymbol { |
|
|
|
|
self.search.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.species` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A function valued property that is the `constructor` function
|
|
|
|
|
/// that is used to create derived objects.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn species_symbol(&self) -> RcSymbol { |
|
|
|
|
self.species.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.split` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A regular expression method that splits a string at the indices
|
|
|
|
|
/// that match the regular expression.
|
|
|
|
|
/// Called by the `String.prototype.split` method.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn split_symbol(&self) -> RcSymbol { |
|
|
|
|
self.split.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.toPrimitive` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A method that converts an object to a corresponding primitive value.
|
|
|
|
|
/// Called by the `ToPrimitive` (`Value::to_primitve`) abstract operation.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn to_primitive_symbol(&self) -> RcSymbol { |
|
|
|
|
self.to_primitive.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.toStringTag` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// A String valued property that is used in the creation of the default
|
|
|
|
|
/// string description of an object.
|
|
|
|
|
/// Accessed by the built-in method `Object.prototype.toString`.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn to_string_tag_symbol(&self) -> RcSymbol { |
|
|
|
|
self.to_string_tag.clone() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The `Symbol.unscopables` well known symbol.
|
|
|
|
|
///
|
|
|
|
|
/// An object valued property whose own and inherited property names are property
|
|
|
|
|
/// names that are excluded from the `with` environment bindings of the associated object.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn unscopables_symbol(&self) -> RcSymbol { |
|
|
|
|
self.unscopables.clone() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Debug, Finalize, Trace, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
|
|
|
|
pub struct Symbol { |
|
|
|
|
hash: u32, |
|
|
|
@ -109,32 +303,32 @@ impl Symbol {
|
|
|
|
|
|
|
|
|
|
/// Initialise the `Symbol` object on the global object.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn init(interpreter: &mut Context) -> (&'static str, Value) { |
|
|
|
|
pub fn init(context: &mut Context) -> (&'static str, Value) { |
|
|
|
|
// Define the Well-Known Symbols
|
|
|
|
|
// https://tc39.es/ecma262/#sec-well-known-symbols
|
|
|
|
|
let symbol_async_iterator = |
|
|
|
|
interpreter.construct_symbol(Some("Symbol.asyncIterator".into())); |
|
|
|
|
let symbol_has_instance = interpreter.construct_symbol(Some("Symbol.hasInstance".into())); |
|
|
|
|
let symbol_is_concat_spreadable = |
|
|
|
|
interpreter.construct_symbol(Some("Symbol.isConcatSpreadable".into())); |
|
|
|
|
let symbol_iterator = interpreter.construct_symbol(Some("Symbol.iterator".into())); |
|
|
|
|
let symbol_match = interpreter.construct_symbol(Some("Symbol.match".into())); |
|
|
|
|
let symbol_match_all = interpreter.construct_symbol(Some("Symbol.matchAll".into())); |
|
|
|
|
let symbol_replace = interpreter.construct_symbol(Some("Symbol.replace".into())); |
|
|
|
|
let symbol_search = interpreter.construct_symbol(Some("Symbol.search".into())); |
|
|
|
|
let symbol_species = interpreter.construct_symbol(Some("Symbol.species".into())); |
|
|
|
|
let symbol_split = interpreter.construct_symbol(Some("Symbol.split".into())); |
|
|
|
|
let symbol_to_primitive = interpreter.construct_symbol(Some("Symbol.toPrimitive".into())); |
|
|
|
|
let symbol_to_string_tag = interpreter.construct_symbol(Some("Symbol.toStringTag".into())); |
|
|
|
|
let symbol_unscopables = interpreter.construct_symbol(Some("Symbol.unscopables".into())); |
|
|
|
|
|
|
|
|
|
let global = interpreter.global_object(); |
|
|
|
|
let well_known_symbols = context.well_known_symbols(); |
|
|
|
|
|
|
|
|
|
let symbol_async_iterator = well_known_symbols.async_iterator_symbol(); |
|
|
|
|
let symbol_has_instance = well_known_symbols.has_instance_symbol(); |
|
|
|
|
let symbol_is_concat_spreadable = well_known_symbols.is_concat_spreadable_symbol(); |
|
|
|
|
let symbol_iterator = well_known_symbols.iterator_symbol(); |
|
|
|
|
let symbol_match = well_known_symbols.match_symbol(); |
|
|
|
|
let symbol_match_all = well_known_symbols.match_all_symbol(); |
|
|
|
|
let symbol_replace = well_known_symbols.replace_symbol(); |
|
|
|
|
let symbol_search = well_known_symbols.search_symbol(); |
|
|
|
|
let symbol_species = well_known_symbols.species_symbol(); |
|
|
|
|
let symbol_split = well_known_symbols.split_symbol(); |
|
|
|
|
let symbol_to_primitive = well_known_symbols.to_primitive_symbol(); |
|
|
|
|
let symbol_to_string_tag = well_known_symbols.to_string_tag_symbol(); |
|
|
|
|
let symbol_unscopables = well_known_symbols.unscopables_symbol(); |
|
|
|
|
|
|
|
|
|
let global = context.global_object(); |
|
|
|
|
let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); |
|
|
|
|
|
|
|
|
|
// Create prototype object
|
|
|
|
|
let prototype = Value::new_object(Some(global)); |
|
|
|
|
|
|
|
|
|
make_builtin_fn(Self::to_string, "toString", &prototype, 0, interpreter); |
|
|
|
|
make_builtin_fn(Self::to_string, "toString", &prototype, 0, context); |
|
|
|
|
|
|
|
|
|
let symbol_object = make_constructor_fn( |
|
|
|
|
Self::NAME, |
|
|
|
|