Browse Source

Cross realm symbols (#1243)

* Cross context symbols

* Remove redundant '_symbol' suffix for well known symbol getters

* Fix symbol equality and hashing

* Add documentation
pull/1250/head
Halid Odat 4 years ago committed by GitHub
parent
commit
087a857865
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      boa/src/builtins/array/array_iterator.rs
  2. 3
      boa/src/builtins/array/mod.rs
  3. 6
      boa/src/builtins/iterable/mod.rs
  4. 4
      boa/src/builtins/json/mod.rs
  5. 3
      boa/src/builtins/map/map_iterator.rs
  6. 3
      boa/src/builtins/map/mod.rs
  7. 6
      boa/src/builtins/math/mod.rs
  8. 4
      boa/src/builtins/object/for_in_iterator.rs
  9. 3
      boa/src/builtins/object/mod.rs
  10. 3
      boa/src/builtins/reflect/mod.rs
  11. 5
      boa/src/builtins/string/mod.rs
  12. 3
      boa/src/builtins/string/string_iterator.rs
  13. 31
      boa/src/builtins/symbol/mod.rs
  14. 41
      boa/src/context.rs
  15. 176
      boa/src/symbol/mod.rs
  16. 3
      boa/src/syntax/ast/node/operator/bin_op/mod.rs
  17. 4
      boa/src/value/mod.rs

3
boa/src/builtins/array/array_iterator.rs

@ -3,6 +3,7 @@ use crate::{
gc::{Finalize, Trace},
object::{GcObject, ObjectData},
property::{Attribute, DataDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result,
};
@ -126,7 +127,7 @@ impl ArrayIterator {
make_builtin_fn(Self::next, "next", &array_iterator, 0, context);
array_iterator.set_prototype_instance(iterator_prototype);
let to_string_tag = context.well_known_symbols().to_string_tag_symbol();
let to_string_tag = WellKnownSymbols::to_string_tag();
let to_string_tag_property = DataDescriptor::new("Array Iterator", Attribute::CONFIGURABLE);
array_iterator.insert(to_string_tag, to_string_tag_property);
array_iterator

3
boa/src/builtins/array/mod.rs

@ -19,6 +19,7 @@ use crate::{
builtins::Number,
object::{ConstructorBuilder, FunctionBuilder, GcObject, ObjectData, PROTOTYPE},
property::{Attribute, DataDescriptor},
symbol::WellKnownSymbols,
value::{same_value_zero, IntegerOrInfinity, Value},
BoaProfiler, Context, Result,
};
@ -42,7 +43,7 @@ impl BuiltIn for Array {
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let symbol_iterator = context.well_known_symbols().iterator_symbol();
let symbol_iterator = WellKnownSymbols::iterator();
let values_function = FunctionBuilder::new(context, Self::values)
.name("values")

6
boa/src/builtins/iterable/mod.rs

@ -5,6 +5,7 @@ use crate::{
builtins::MapIterator,
object::{GcObject, ObjectInitializer},
property::{Attribute, DataDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
};
@ -79,8 +80,7 @@ pub fn create_iter_result_object(context: &mut Context, value: Value, done: bool
/// Get an iterator record
pub fn get_iterator(context: &mut Context, iterable: Value) -> Result<IteratorRecord> {
let iterator_function =
iterable.get_field(context.well_known_symbols().iterator_symbol(), context)?;
let iterator_function = iterable.get_field(WellKnownSymbols::iterator(), context)?;
if iterator_function.is_null_or_undefined() {
return Err(context.construct_type_error("Not an iterable"));
}
@ -101,7 +101,7 @@ pub fn get_iterator(context: &mut Context, iterable: Value) -> Result<IteratorRe
fn create_iterator_prototype(context: &mut Context) -> GcObject {
let _timer = BoaProfiler::global().start_event("Iterator Prototype", "init");
let symbol_iterator = context.well_known_symbols().iterator_symbol();
let symbol_iterator = WellKnownSymbols::iterator();
let iterator_prototype = ObjectInitializer::new(context)
.function(
|v, _, _| Ok(v.clone()),

4
boa/src/builtins/json/mod.rs

@ -13,7 +13,6 @@
//! [json]: https://www.json.org/json-en.html
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
use crate::object::Object;
use crate::{
builtins::BuiltIn,
object::ObjectInitializer,
@ -21,6 +20,7 @@ use crate::{
value::IntegerOrInfinity,
BoaProfiler, Context, Result, Value,
};
use crate::{object::Object, symbol::WellKnownSymbols};
use serde::Serialize;
use serde_json::{self, ser::PrettyFormatter, Serializer, Value as JSONValue};
@ -41,7 +41,7 @@ impl BuiltIn for Json {
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let to_string_tag = context.well_known_symbols().to_string_tag_symbol();
let to_string_tag = WellKnownSymbols::to_string_tag();
let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;

3
boa/src/builtins/map/map_iterator.rs

@ -2,6 +2,7 @@ use crate::{
builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, Value},
object::{GcObject, ObjectData},
property::{Attribute, DataDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result,
};
use gc::{Finalize, Trace};
@ -146,7 +147,7 @@ impl MapIterator {
make_builtin_fn(Self::next, "next", &map_iterator, 0, context);
map_iterator.set_prototype_instance(iterator_prototype);
let to_string_tag = context.well_known_symbols().to_string_tag_symbol();
let to_string_tag = WellKnownSymbols::to_string_tag();
let to_string_tag_property = DataDescriptor::new("Map Iterator", Attribute::CONFIGURABLE);
map_iterator.insert(to_string_tag, to_string_tag_property);
map_iterator

3
boa/src/builtins/map/mod.rs

@ -4,6 +4,7 @@ use crate::{
builtins::BuiltIn,
object::{ConstructorBuilder, FunctionBuilder, ObjectData, PROTOTYPE},
property::{Attribute, DataDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
};
use ordered_map::OrderedMap;
@ -28,7 +29,7 @@ impl BuiltIn for Map {
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let iterator_symbol = context.well_known_symbols().iterator_symbol();
let iterator_symbol = WellKnownSymbols::iterator();
let entries_function = FunctionBuilder::new(context, Self::entries)
.name("entries")

6
boa/src/builtins/math/mod.rs

@ -12,8 +12,8 @@
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math
use crate::{
builtins::BuiltIn, object::ObjectInitializer, property::Attribute, BoaProfiler, Context,
Result, Value,
builtins::BuiltIn, object::ObjectInitializer, property::Attribute, symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
};
#[cfg(test)]
@ -34,7 +34,7 @@ impl BuiltIn for Math {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
use std::f64;
let to_string_tag = context.well_known_symbols().to_string_tag_symbol();
let to_string_tag = WellKnownSymbols::to_string_tag();
let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
let object = ObjectInitializer::new(context)

4
boa/src/builtins/object/for_in_iterator.rs

@ -1,4 +1,3 @@
use crate::property::PropertyKey;
use crate::value::RcString;
use crate::{
builtins::{function::make_builtin_fn, iterable::create_iter_result_object},
@ -7,6 +6,7 @@ use crate::{
property::{Attribute, DataDescriptor},
BoaProfiler, Context, Result, Value,
};
use crate::{property::PropertyKey, symbol::WellKnownSymbols};
use rustc_hash::FxHashSet;
use std::collections::VecDeque;
@ -133,7 +133,7 @@ impl ForInIterator {
make_builtin_fn(Self::next, "next", &for_in_iterator, 0, context);
for_in_iterator.set_prototype_instance(iterator_prototype);
let to_string_tag = context.well_known_symbols().to_string_tag_symbol();
let to_string_tag = WellKnownSymbols::to_string_tag();
let to_string_tag_property =
DataDescriptor::new("For In Iterator", Attribute::CONFIGURABLE);
for_in_iterator.insert(to_string_tag, to_string_tag_property);

3
boa/src/builtins/object/mod.rs

@ -21,6 +21,7 @@ use crate::{
property::Attribute,
property::DataDescriptor,
property::PropertyDescriptor,
symbol::WellKnownSymbols,
value::{same_value, Type, Value},
BoaProfiler, Context, Result,
};
@ -433,7 +434,7 @@ impl Object {
};
let tag = o.get(
&context.well_known_symbols().to_string_tag_symbol().into(),
&WellKnownSymbols::to_string_tag().into(),
o.clone().into(),
context,
)?;

3
boa/src/builtins/reflect/mod.rs

@ -14,6 +14,7 @@ use crate::{
builtins::{self, BuiltIn},
object::{Object, ObjectData, ObjectInitializer},
property::{Attribute, DataDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
};
@ -34,7 +35,7 @@ impl BuiltIn for Reflect {
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let to_string_tag = context.well_known_symbols().to_string_tag_symbol();
let to_string_tag = WellKnownSymbols::to_string_tag();
let object = ObjectInitializer::new(context)
.function(Self::apply, "apply", 3)

5
boa/src/builtins/string/mod.rs

@ -20,6 +20,7 @@ use crate::{
builtins::{string::string_iterator::StringIterator, Array, BuiltIn, RegExp},
object::{ConstructorBuilder, Object, ObjectData},
property::Attribute,
symbol::WellKnownSymbols,
value::{RcString, Value},
BoaProfiler, Context, Result,
};
@ -94,7 +95,7 @@ impl BuiltIn for String {
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let symbol_iterator = context.well_known_symbols().iterator_symbol();
let symbol_iterator = WellKnownSymbols::iterator();
let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
let string_object = ConstructorBuilder::with_standard_object(
@ -1215,7 +1216,7 @@ impl String {
if let Some(result) = separator
.and_then(|separator| separator.as_object())
.and_then(|separator| {
let key = context.well_known_symbols().split_symbol();
let key = WellKnownSymbols::split();
match separator.get_method(context, key) {
Ok(splitter) => splitter.map(|splitter| {

3
boa/src/builtins/string/string_iterator.rs

@ -5,6 +5,7 @@ use crate::{
gc::{Finalize, Trace},
object::{GcObject, ObjectData},
property::{Attribute, DataDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
};
@ -77,7 +78,7 @@ impl StringIterator {
make_builtin_fn(Self::next, "next", &array_iterator, 0, context);
array_iterator.set_prototype_instance(iterator_prototype);
let to_string_tag = context.well_known_symbols().to_string_tag_symbol();
let to_string_tag = WellKnownSymbols::to_string_tag();
let to_string_tag_property =
DataDescriptor::new("String Iterator", Attribute::CONFIGURABLE);
array_iterator.insert(to_string_tag, to_string_tag_property);

31
boa/src/builtins/symbol/mod.rs

@ -22,7 +22,7 @@ use crate::{
builtins::BuiltIn,
object::{ConstructorBuilder, FunctionBuilder},
property::Attribute,
symbol::RcSymbol,
symbol::{RcSymbol, WellKnownSymbols},
value::Value,
BoaProfiler, Context, Result,
};
@ -40,22 +40,19 @@ impl BuiltIn for Symbol {
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// https://tc39.es/ecma262/#sec-well-known-symbols
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 symbol_async_iterator = WellKnownSymbols::async_iterator();
let symbol_has_instance = WellKnownSymbols::has_instance();
let symbol_is_concat_spreadable = WellKnownSymbols::is_concat_spreadable();
let symbol_iterator = WellKnownSymbols::iterator();
let symbol_match = WellKnownSymbols::match_();
let symbol_match_all = WellKnownSymbols::match_all();
let symbol_replace = WellKnownSymbols::replace();
let symbol_search = WellKnownSymbols::search();
let symbol_species = WellKnownSymbols::species();
let symbol_split = WellKnownSymbols::split();
let symbol_to_primitive = WellKnownSymbols::to_primitive();
let symbol_to_string_tag = WellKnownSymbols::to_string_tag();
let symbol_unscopables = WellKnownSymbols::unscopables();
let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;

41
boa/src/context.rs

@ -11,7 +11,7 @@ use crate::{
object::{GcObject, Object, PROTOTYPE},
property::{Attribute, DataDescriptor, PropertyKey},
realm::Realm,
symbol::{RcSymbol, Symbol, WellKnownSymbols},
symbol::{RcSymbol, Symbol},
syntax::{
ast::{
node::{
@ -215,18 +215,10 @@ pub struct Context {
/// The current executor.
executor: Interpreter,
/// Symbol hash.
///
/// For now this is an incremented u64 number.
symbol_count: u64,
/// console object state.
#[cfg(feature = "console")]
console: Console,
/// Cached well known symbols
well_known_symbols: WellKnownSymbols,
/// Cached iterator prototypes.
iterator_prototypes: IteratorPrototypes,
@ -241,14 +233,11 @@ impl Default for Context {
fn default() -> Self {
let realm = Realm::create();
let executor = Interpreter::new();
let (well_known_symbols, symbol_count) = WellKnownSymbols::new();
let mut context = Self {
realm,
executor,
symbol_count,
#[cfg(feature = "console")]
console: Console::default(),
well_known_symbols,
iterator_prototypes: IteratorPrototypes::default(),
standard_objects: Default::default(),
trace: false,
@ -296,20 +285,10 @@ impl Context {
builtins::init(self);
}
/// Generates a new `Symbol` internal hash.
///
/// This currently is an incremented value.
#[inline]
fn generate_hash(&mut self) -> u64 {
let hash = self.symbol_count;
self.symbol_count += 1;
hash
}
/// Construct a new `Symbol` with an optional description.
#[inline]
pub fn construct_symbol(&mut self, description: Option<RcString>) -> RcSymbol {
RcSymbol::from(Symbol::new(self.generate_hash(), description))
RcSymbol::from(Symbol::new(description))
}
/// Construct an empty object.
@ -709,22 +688,6 @@ impl Context {
result
}
/// Returns a structure that contains the JavaScript well known symbols.
///
/// # Examples
/// ```
///# use boa::Context;
/// let mut context = Context::new();
///
/// let iterator = context.well_known_symbols().iterator_symbol();
/// assert_eq!(iterator.description(), Some("Symbol.iterator"));
/// ```
/// This is equivalent to `let iterator = Symbol.iterator` in JavaScript.
#[inline]
pub fn well_known_symbols(&self) -> &WellKnownSymbols {
&self.well_known_symbols
}
/// Return the cached iterator prototypes.
#[inline]
pub fn iterator_prototypes(&self) -> &IteratorPrototypes {

176
boa/src/symbol/mod.rs

@ -21,10 +21,23 @@ use crate::{
gc::{Finalize, Trace},
value::RcString,
};
use std::{
cell::Cell,
hash::{Hash, Hasher},
};
pub use rcsymbol::RcSymbol;
/// A structure that contains the JavaScript well known symbols.
///
/// # Examples
/// ```
///# use boa::symbol::WellKnownSymbols;
///
/// let iterator = WellKnownSymbols::iterator();
/// assert_eq!(iterator.description(), Some("Symbol.iterator"));
/// ```
/// This is equivalent to `let iterator = Symbol.iterator` in JavaScript.
#[derive(Debug, Clone)]
pub struct WellKnownSymbols {
async_iterator: RcSymbol,
@ -42,56 +55,69 @@ pub struct WellKnownSymbols {
unscopables: RcSymbol,
}
/// Reserved number of symbols.
///
/// This is where the well known symbol live
/// and internal engine symbols.
const RESERVED_SYMBOL_HASHES: u64 = 128;
thread_local! {
/// Cached well known symbols
static WELL_KNOW_SYMBOLS: WellKnownSymbols = WellKnownSymbols::new();
/// Symbol hash.
///
/// For now this is an incremented u64 number.
static SYMBOL_HASH_COUNT: Cell<u64> = Cell::new(RESERVED_SYMBOL_HASHES);
}
impl WellKnownSymbols {
pub(crate) fn new() -> (Self, u64) {
/// Create the well known symbols.
fn new() -> Self {
let mut count = 0;
let async_iterator = Symbol::new(count, Some("Symbol.asyncIterator".into())).into();
let async_iterator = Symbol::with_hash(count, Some("Symbol.asyncIterator".into())).into();
count += 1;
let has_instance = Symbol::new(count, Some("Symbol.hasInstance".into())).into();
let has_instance = Symbol::with_hash(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();
Symbol::with_hash(count, Some("Symbol.isConcatSpreadable".into())).into();
count += 1;
let match_ = Symbol::new(count, Some("Symbol.match".into())).into();
let iterator = Symbol::with_hash(count, Some("Symbol.iterator".into())).into();
count += 1;
let match_all = Symbol::new(count, Some("Symbol.matchAll".into())).into();
let match_ = Symbol::with_hash(count, Some("Symbol.match".into())).into();
count += 1;
let replace = Symbol::new(count, Some("Symbol.replace".into())).into();
let match_all = Symbol::with_hash(count, Some("Symbol.matchAll".into())).into();
count += 1;
let search = Symbol::new(count, Some("Symbol.search".into())).into();
let replace = Symbol::with_hash(count, Some("Symbol.replace".into())).into();
count += 1;
let species = Symbol::new(count, Some("Symbol.species".into())).into();
let search = Symbol::with_hash(count, Some("Symbol.search".into())).into();
count += 1;
let split = Symbol::new(count, Some("Symbol.split".into())).into();
let species = Symbol::with_hash(count, Some("Symbol.species".into())).into();
count += 1;
let to_primitive = Symbol::new(count, Some("Symbol.toPrimitive".into())).into();
let split = Symbol::with_hash(count, Some("Symbol.split".into())).into();
count += 1;
let to_string_tag = Symbol::new(count, Some("Symbol.toStringTag".into())).into();
let to_primitive = Symbol::with_hash(count, Some("Symbol.toPrimitive".into())).into();
count += 1;
let unscopables = Symbol::new(count, Some("Symbol.unscopables".into())).into();
let to_string_tag = Symbol::with_hash(count, Some("Symbol.toStringTag".into())).into();
count += 1;
let unscopables = Symbol::with_hash(count, Some("Symbol.unscopables".into())).into();
(
Self {
async_iterator,
has_instance,
is_concat_spreadable,
iterator,
match_,
match_all,
replace,
search,
species,
split,
to_primitive,
to_string_tag,
unscopables,
},
count,
)
Self {
async_iterator,
has_instance,
is_concat_spreadable,
iterator,
match_,
match_all,
replace,
search,
species,
split,
to_primitive,
to_string_tag,
unscopables,
}
}
/// The `Symbol.asyncIterator` well known symbol.
@ -99,8 +125,8 @@ impl WellKnownSymbols {
/// 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()
pub fn async_iterator() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.async_iterator.clone())
}
/// The `Symbol.hasInstance` well known symbol.
@ -109,8 +135,8 @@ impl WellKnownSymbols {
/// 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.has_instance.clone()
pub fn has_instance() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.has_instance.clone())
}
/// The `Symbol.isConcatSpreadable` well known symbol.
@ -119,8 +145,8 @@ impl WellKnownSymbols {
/// 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()
pub fn is_concat_spreadable() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.is_concat_spreadable.clone())
}
/// The `Symbol.iterator` well known symbol.
@ -128,8 +154,8 @@ impl WellKnownSymbols {
/// 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()
pub fn iterator() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.iterator.clone())
}
/// The `Symbol.match` well known symbol.
@ -137,8 +163,8 @@ impl WellKnownSymbols {
/// 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()
pub fn match_() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.match_.clone())
}
/// The `Symbol.matchAll` well known symbol.
@ -147,8 +173,8 @@ impl WellKnownSymbols {
/// 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()
pub fn match_all() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.match_all.clone())
}
/// The `Symbol.replace` well known symbol.
@ -156,8 +182,8 @@ impl WellKnownSymbols {
/// 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()
pub fn replace() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.replace.clone())
}
/// The `Symbol.search` well known symbol.
@ -166,8 +192,8 @@ impl WellKnownSymbols {
/// string that matches the regular expression.
/// Called by the `String.prototype.search` method.
#[inline]
pub fn search_symbol(&self) -> RcSymbol {
self.search.clone()
pub fn search() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.search.clone())
}
/// The `Symbol.species` well known symbol.
@ -175,8 +201,8 @@ impl WellKnownSymbols {
/// 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()
pub fn species() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.species.clone())
}
/// The `Symbol.split` well known symbol.
@ -185,8 +211,8 @@ impl WellKnownSymbols {
/// that match the regular expression.
/// Called by the `String.prototype.split` method.
#[inline]
pub fn split_symbol(&self) -> RcSymbol {
self.split.clone()
pub fn split() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.split.clone())
}
/// The `Symbol.toPrimitive` well known symbol.
@ -194,8 +220,8 @@ impl WellKnownSymbols {
/// 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()
pub fn to_primitive() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.to_primitive.clone())
}
/// The `Symbol.toStringTag` well known symbol.
@ -204,8 +230,8 @@ impl WellKnownSymbols {
/// 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()
pub fn to_string_tag() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.to_string_tag.clone())
}
/// The `Symbol.unscopables` well known symbol.
@ -213,19 +239,31 @@ impl WellKnownSymbols {
/// 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()
pub fn unscopables() -> RcSymbol {
WELL_KNOW_SYMBOLS.with(|symbols| symbols.unscopables.clone())
}
}
#[derive(Debug, Finalize, Trace, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Debug, Finalize, Trace, Clone, Eq, PartialOrd, Ord)]
pub struct Symbol {
pub(crate) hash: u64,
pub(crate) description: Option<RcString>,
}
impl Symbol {
pub(crate) fn new(hash: u64, description: Option<RcString>) -> Self {
/// Create a new symbol with a specified hash and description.
fn with_hash(hash: u64, description: Option<RcString>) -> Self {
Self { hash, description }
}
/// Create a new symbol.
#[inline]
pub fn new(description: Option<RcString>) -> Self {
let hash = SYMBOL_HASH_COUNT.with(|count| {
let hash = count.get();
count.set(hash + 1);
hash
});
Self { hash, description }
}
@ -236,8 +274,24 @@ impl Symbol {
}
/// Returns the `Symbol`s hash.
///
/// The hash is guaranteed to be unique.
#[inline]
pub fn hash(&self) -> u64 {
self.hash
}
}
impl PartialEq for Symbol {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.hash == other.hash
}
}
impl Hash for Symbol {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.hash.hash(state);
}
}

3
boa/src/syntax/ast/node/operator/bin_op/mod.rs

@ -1,6 +1,7 @@
use crate::{
exec::Executable,
gc::{Finalize, Trace},
symbol::WellKnownSymbols,
syntax::ast::{
node::Node,
op::{self, AssignOp, BitOp, CompOp, LogOp, NumOp},
@ -153,7 +154,7 @@ impl Executable for BinOp {
}
CompOp::InstanceOf => {
if let Some(object) = y.as_object() {
let key = context.well_known_symbols().has_instance_symbol();
let key = WellKnownSymbols::has_instance();
match object.get_method(context, key)? {
Some(instance_of_handler) => {

4
boa/src/value/mod.rs

@ -13,7 +13,7 @@ use crate::{
},
object::{GcObject, Object, ObjectData},
property::{Attribute, DataDescriptor, PropertyDescriptor, PropertyKey},
symbol::RcSymbol,
symbol::{RcSymbol, WellKnownSymbols},
BoaProfiler, Context, Result,
};
use gc::{Finalize, Trace};
@ -520,7 +520,7 @@ impl Value {
// 2. If Type(input) is Object, then
if let Value::Object(obj) = self {
if let Some(exotic_to_prim) =
obj.get_method(context, context.well_known_symbols().to_primitive_symbol())?
obj.get_method(context, WellKnownSymbols::to_primitive())?
{
let hint = match preferred_type {
PreferredType::String => "string",

Loading…
Cancel
Save