Browse Source

Separate Symbol builtin (#1234)

pull/1236/head
Halid Odat 4 years ago committed by GitHub
parent
commit
db3b6c5213
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 221
      boa/src/builtins/symbol/mod.rs
  2. 4
      boa/src/context.rs
  3. 1
      boa/src/lib.rs
  4. 2
      boa/src/object/iter.rs
  5. 3
      boa/src/object/mod.rs
  6. 3
      boa/src/property/mod.rs
  7. 243
      boa/src/symbol/mod.rs
  8. 2
      boa/src/symbol/rcsymbol.rs
  9. 3
      boa/src/value/mod.rs

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

@ -20,218 +20,15 @@ mod tests;
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
gc::{Finalize, Trace},
object::{ConstructorBuilder, FunctionBuilder}, object::{ConstructorBuilder, FunctionBuilder},
property::Attribute, property::Attribute,
value::{RcString, RcSymbol, Value}, symbol::RcSymbol,
value::Value,
BoaProfiler, Context, Result, BoaProfiler, Context, Result,
}; };
/// A structure that contains the JavaScript well known symbols. #[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)] pub struct Symbol;
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, u64) {
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.has_instance.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: u64,
description: Option<RcString>,
}
impl Symbol {
pub(crate) fn new(hash: u64, description: Option<RcString>) -> Self {
Self { hash, description }
}
}
impl BuiltIn for Symbol { impl BuiltIn for Symbol {
const NAME: &'static str = "Symbol"; const NAME: &'static str = "Symbol";
@ -307,16 +104,6 @@ impl Symbol {
/// The amount of arguments this function object takes. /// The amount of arguments this function object takes.
pub(crate) const LENGTH: usize = 0; pub(crate) const LENGTH: usize = 0;
/// Returns the `Symbol`s description.
pub fn description(&self) -> Option<&str> {
self.description.as_deref()
}
/// Returns the `Symbol`s hash.
pub fn hash(&self) -> u64 {
self.hash
}
/// The `Symbol()` constructor returns a value of type symbol. /// The `Symbol()` constructor returns a value of type symbol.
/// ///
/// It is incomplete as a constructor because it does not support /// It is incomplete as a constructor because it does not support

4
boa/src/context.rs

@ -5,13 +5,13 @@ use crate::{
self, self,
function::{Function, FunctionFlags, NativeFunction}, function::{Function, FunctionFlags, NativeFunction},
iterable::IteratorPrototypes, iterable::IteratorPrototypes,
symbol::{Symbol, WellKnownSymbols},
}, },
class::{Class, ClassBuilder}, class::{Class, ClassBuilder},
exec::Interpreter, exec::Interpreter,
object::{GcObject, Object, PROTOTYPE}, object::{GcObject, Object, PROTOTYPE},
property::{Attribute, DataDescriptor, PropertyKey}, property::{Attribute, DataDescriptor, PropertyKey},
realm::Realm, realm::Realm,
symbol::{RcSymbol, Symbol, WellKnownSymbols},
syntax::{ syntax::{
ast::{ ast::{
node::{ node::{
@ -22,7 +22,7 @@ use crate::{
}, },
Parser, Parser,
}, },
value::{RcString, RcSymbol, Value}, value::{RcString, Value},
BoaProfiler, Executable, Result, BoaProfiler, Executable, Result,
}; };

1
boa/src/lib.rs

@ -54,6 +54,7 @@ pub mod profiler;
pub mod property; pub mod property;
pub mod realm; pub mod realm;
// syntax module has a lot of acronyms // syntax module has a lot of acronyms
pub mod symbol;
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
pub mod syntax; pub mod syntax;
pub mod value; pub mod value;

2
boa/src/object/iter.rs

@ -1,5 +1,5 @@
use super::{Object, PropertyDescriptor, PropertyKey}; use super::{Object, PropertyDescriptor, PropertyKey};
use crate::value::{RcString, RcSymbol}; use crate::{symbol::RcSymbol, value::RcString};
use std::{collections::hash_map, iter::FusedIterator}; use std::{collections::hash_map, iter::FusedIterator};
impl Object { impl Object {

3
boa/src/object/mod.rs

@ -12,7 +12,8 @@ use crate::{
context::StandardConstructor, context::StandardConstructor,
gc::{Finalize, Trace}, gc::{Finalize, Trace},
property::{AccessorDescriptor, Attribute, DataDescriptor, PropertyDescriptor, PropertyKey}, property::{AccessorDescriptor, Attribute, DataDescriptor, PropertyDescriptor, PropertyKey},
value::{same_value, RcBigInt, RcString, RcSymbol, Value}, symbol::RcSymbol,
value::{same_value, RcBigInt, RcString, Value},
BoaProfiler, Context, BoaProfiler, Context,
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;

3
boa/src/property/mod.rs

@ -17,7 +17,8 @@
use crate::{ use crate::{
gc::{Finalize, Trace}, gc::{Finalize, Trace},
object::GcObject, object::GcObject,
value::{RcString, RcSymbol, Value}, symbol::RcSymbol,
value::{RcString, Value},
}; };
use std::{convert::TryFrom, fmt}; use std::{convert::TryFrom, fmt};

243
boa/src/symbol/mod.rs

@ -0,0 +1,243 @@
//! This module implements the global `Symbol` object.
//!
//! The data type symbol is a primitive data type.
//! The `Symbol()` function returns a value of type symbol, has static properties that expose
//! several members of built-in objects, has static methods that expose the global symbol registry,
//! and resembles a built-in object class, but is incomplete as a constructor because it does not
//! support the syntax "`new Symbol()`".
//!
//! Every symbol value returned from `Symbol()` is unique.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [ECMAScript reference][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-symbol-value
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
mod rcsymbol;
use crate::{
gc::{Finalize, Trace},
value::RcString,
};
pub use rcsymbol::RcSymbol;
/// 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, u64) {
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.has_instance.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 {
pub(crate) hash: u64,
pub(crate) description: Option<RcString>,
}
impl Symbol {
pub(crate) fn new(hash: u64, description: Option<RcString>) -> Self {
Self { hash, description }
}
/// Returns the `Symbol`s description.
#[inline]
pub fn description(&self) -> Option<&str> {
self.description.as_deref()
}
/// Returns the `Symbol`s hash.
#[inline]
pub fn hash(&self) -> u64 {
self.hash
}
}

2
boa/src/value/rcsymbol.rs → boa/src/symbol/rcsymbol.rs

@ -1,6 +1,6 @@
use crate::{ use crate::{
builtins::Symbol,
gc::{empty_trace, Finalize, Trace}, gc::{empty_trace, Finalize, Trace},
symbol::Symbol,
}; };
use std::{ use std::{

3
boa/src/value/mod.rs

@ -13,6 +13,7 @@ use crate::{
}, },
object::{GcObject, Object, ObjectData}, object::{GcObject, Object, ObjectData},
property::{Attribute, DataDescriptor, PropertyDescriptor, PropertyKey}, property::{Attribute, DataDescriptor, PropertyDescriptor, PropertyKey},
symbol::RcSymbol,
BoaProfiler, Context, Result, BoaProfiler, Context, Result,
}; };
use gc::{Finalize, Trace}; use gc::{Finalize, Trace};
@ -31,7 +32,6 @@ mod hash;
mod operations; mod operations;
mod rcbigint; mod rcbigint;
mod rcstring; mod rcstring;
mod rcsymbol;
mod r#type; mod r#type;
pub use conversions::*; pub use conversions::*;
@ -42,7 +42,6 @@ pub use operations::*;
pub use r#type::Type; pub use r#type::Type;
pub use rcbigint::RcBigInt; pub use rcbigint::RcBigInt;
pub use rcstring::RcString; pub use rcstring::RcString;
pub use rcsymbol::RcSymbol;
/// A Javascript value /// A Javascript value
#[derive(Trace, Finalize, Debug, Clone)] #[derive(Trace, Finalize, Debug, Clone)]

Loading…
Cancel
Save