Browse Source

Merge pull request #587 from joshwd36/Well-Known-Symbols

Implement Well-Known Symbols
pull/599/head
Paul Lancaster 4 years ago committed by GitHub
parent
commit
7b3f42de54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      boa/src/builtins/array/mod.rs
  2. 3
      boa/src/builtins/bigint/mod.rs
  3. 3
      boa/src/builtins/boolean/mod.rs
  4. 3
      boa/src/builtins/console/mod.rs
  5. 3
      boa/src/builtins/error/mod.rs
  6. 3
      boa/src/builtins/error/range.rs
  7. 3
      boa/src/builtins/error/reference.rs
  8. 3
      boa/src/builtins/error/syntax.rs
  9. 3
      boa/src/builtins/error/type.rs
  10. 3
      boa/src/builtins/function/mod.rs
  11. 5
      boa/src/builtins/global_this/mod.rs
  12. 4
      boa/src/builtins/infinity/mod.rs
  13. 3
      boa/src/builtins/json/mod.rs
  14. 3
      boa/src/builtins/map/mod.rs
  15. 3
      boa/src/builtins/math/mod.rs
  16. 14
      boa/src/builtins/mod.rs
  17. 4
      boa/src/builtins/nan/mod.rs
  18. 3
      boa/src/builtins/number/mod.rs
  19. 3
      boa/src/builtins/object/mod.rs
  20. 3
      boa/src/builtins/regexp/mod.rs
  21. 3
      boa/src/builtins/string/mod.rs
  22. 54
      boa/src/builtins/symbol/mod.rs
  23. 4
      boa/src/builtins/undefined/mod.rs
  24. 2
      boa/src/builtins/value/mod.rs
  25. 24
      boa/src/exec/mod.rs
  26. 19
      boa/src/realm.rs

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

@ -1114,7 +1114,8 @@ impl Array {
/// Initialise the `Array` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create prototype

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

@ -200,7 +200,8 @@ impl BigInt {
/// Initialise the `BigInt` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let prototype = Value::new_object(Some(global));

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

@ -98,7 +98,8 @@ impl Boolean {
/// Initialise the `Boolean` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create Prototype

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

@ -489,7 +489,8 @@ impl Console {
/// Initialise the `console` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let console = Value::new_object(Some(global));

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

@ -76,7 +76,8 @@ impl Error {
/// Initialise the global object with the `Error` object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let prototype = Value::new_object(Some(global));

3
boa/src/builtins/error/range.rs

@ -62,7 +62,8 @@ impl RangeError {
/// Initialise the global object with the `RangeError` object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let prototype = Value::new_object(Some(global));

3
boa/src/builtins/error/reference.rs

@ -60,7 +60,8 @@ impl ReferenceError {
}
/// Initialise the global object with the `ReferenceError` object.
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let prototype = Value::new_object(Some(global));

3
boa/src/builtins/error/syntax.rs

@ -64,7 +64,8 @@ impl SyntaxError {
/// Initialise the global object with the `SyntaxError` object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let prototype = Value::new_object(Some(global));

3
boa/src/builtins/error/type.rs

@ -68,7 +68,8 @@ impl TypeError {
/// Initialise the global object with the `RangeError` object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let prototype = Value::new_object(Some(global));

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

@ -533,7 +533,8 @@ where
/// Initialise the `Function` object on the global object.
#[inline]
pub fn init(global: &Value) -> (&str, Value) {
pub fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event("function", "init");
let prototype = Value::new_object(Some(global));

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

@ -10,7 +10,7 @@
//! [spec]: https://tc39.es/ecma262/#sec-globalthis
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis
use crate::{builtins::value::Value, BoaProfiler};
use crate::{builtins::value::Value, BoaProfiler, Interpreter};
#[cfg(test)]
mod tests;
@ -24,7 +24,8 @@ impl GlobalThis {
/// Initialize the `globalThis` property on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, global.clone())

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

@ -12,7 +12,7 @@
#[cfg(test)]
mod tests;
use crate::{builtins::value::Value, BoaProfiler};
use crate::{builtins::value::Value, BoaProfiler, Interpreter};
/// JavaScript global `Infinity` property.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -24,7 +24,7 @@ impl Infinity {
/// Initialize the `Infinity` property on the global object.
#[inline]
pub(crate) fn init(_: &Value) -> (&str, Value) {
pub(crate) fn init(_interpreter: &mut Interpreter) -> (&'static str, Value) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, Value::from(f64::INFINITY))

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

@ -172,7 +172,8 @@ impl Json {
/// Initialise the `JSON` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let json = Value::new_object(Some(global));

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

@ -284,7 +284,8 @@ impl Map {
}
/// Initialise the `Map` object on the global object.
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create prototype

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

@ -697,7 +697,8 @@ impl Math {
/// Initialise the `Math` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, Self::create(global))

14
boa/src/builtins/mod.rs

@ -40,10 +40,11 @@ pub(crate) use self::{
undefined::Undefined,
value::{ResultValue, Value},
};
use crate::Interpreter;
/// Initializes builtin objects and functions
#[inline]
pub fn init(global: &Value) {
pub fn init(interpreter: &mut Interpreter) {
let globals = [
// The `Function` global must be initialized before other types.
function::init,
@ -72,13 +73,14 @@ pub fn init(global: &Value) {
Undefined::init,
];
match global {
Value::Object(ref global_object) => {
for init in &globals {
let (name, value) = init(global);
for init in &globals {
let (name, value) = init(interpreter);
let global = interpreter.global();
match global {
Value::Object(ref global_object) => {
global_object.borrow_mut().insert_field(name, value);
}
_ => unreachable!("expect global object"),
}
_ => unreachable!("expect global object"),
}
}

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

@ -13,7 +13,7 @@
#[cfg(test)]
mod tests;
use crate::{builtins::value::Value, BoaProfiler};
use crate::{builtins::value::Value, BoaProfiler, Interpreter};
/// JavaScript global `NaN` property.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -25,7 +25,7 @@ impl NaN {
/// Initialize the `NaN` property on the global object.
#[inline]
pub(crate) fn init(_: &Value) -> (&str, Value) {
pub(crate) fn init(_interpreter: &mut Interpreter) -> (&'static str, Value) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, Value::from(f64::NAN))

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

@ -727,7 +727,8 @@ impl Number {
/// Initialise the `Number` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let prototype = Value::new_object(Some(global));

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

@ -577,7 +577,8 @@ pub fn property_is_enumerable(this: &Value, args: &[Value], ctx: &mut Interprete
/// Initialise the `Object` object on the global object.
#[inline]
pub fn init(global: &Value) -> (&str, Value) {
pub fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event("object", "init");
let prototype = Value::new_object(None);

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

@ -492,7 +492,8 @@ impl RegExp {
/// Initialise the `RegExp` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, Self::create(global))

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

@ -1026,7 +1026,8 @@ impl String {
/// Initialise the `String` object on the global object.
#[inline]
pub(crate) fn init(global: &Value) -> (&str, Value) {
pub(crate) fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create `String` `prototype`

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

@ -100,7 +100,42 @@ impl Symbol {
/// Initialise the `Symbol` object on the global object.
#[inline]
pub fn init(global: &Value) -> (&str, Value) {
pub fn init(interpreter: &mut Interpreter) -> (&'static str, Value) {
// Define the Well-Known Symbols
// https://tc39.es/ecma262/#sec-well-known-symbols
let symbol_async_iterator = Symbol(
Some("Symbol.asyncIterator".into()),
interpreter.generate_hash(),
);
let symbol_has_instance = Symbol(
Some("Symbol.hasInstance".into()),
interpreter.generate_hash(),
);
let symbol_is_concat_spreadable = Symbol(
Some("Symbol.isConcatSpreadable".into()),
interpreter.generate_hash(),
);
let symbol_iterator = Symbol(Some("Symbol.iterator".into()), interpreter.generate_hash());
let symbol_match = Symbol(Some("Symbol.match".into()), interpreter.generate_hash());
let symbol_match_all = Symbol(Some("Symbol.matchAll".into()), interpreter.generate_hash());
let symbol_replace = Symbol(Some("Symbol.replace".into()), interpreter.generate_hash());
let symbol_search = Symbol(Some("Symbol.search".into()), interpreter.generate_hash());
let symbol_species = Symbol(Some("Symbol.species".into()), interpreter.generate_hash());
let symbol_split = Symbol(Some("Symbol.split".into()), interpreter.generate_hash());
let symbol_to_primitive = Symbol(
Some("Symbol.toPrimitive".into()),
interpreter.generate_hash(),
);
let symbol_to_string_tag = Symbol(
Some("Symbol.toStringTag".into()),
interpreter.generate_hash(),
);
let symbol_unscopables = Symbol(
Some("Symbol.unscopables".into()),
interpreter.generate_hash(),
);
let global = interpreter.global();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create prototype object
@ -118,6 +153,23 @@ impl Symbol {
true,
);
symbol_object.set_field("asyncIterator", Value::symbol(symbol_async_iterator));
symbol_object.set_field("hasInstance", Value::symbol(symbol_has_instance));
symbol_object.set_field(
"isConcatSpreadable",
Value::symbol(symbol_is_concat_spreadable),
);
symbol_object.set_field("iterator", Value::symbol(symbol_iterator));
symbol_object.set_field("match", Value::symbol(symbol_match));
symbol_object.set_field("matchAll", Value::symbol(symbol_match_all));
symbol_object.set_field("replace", Value::symbol(symbol_replace));
symbol_object.set_field("search", Value::symbol(symbol_search));
symbol_object.set_field("species", Value::symbol(symbol_species));
symbol_object.set_field("split", Value::symbol(symbol_split));
symbol_object.set_field("toPrimitive", Value::symbol(symbol_to_primitive));
symbol_object.set_field("toStringTag", Value::symbol(symbol_to_string_tag));
symbol_object.set_field("unscopables", Value::symbol(symbol_unscopables));
(Self::NAME, symbol_object)
}
}

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

@ -12,7 +12,7 @@
#[cfg(test)]
mod tests;
use crate::{builtins::value::Value, BoaProfiler};
use crate::{builtins::value::Value, BoaProfiler, Interpreter};
/// JavaScript global `undefined` property.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -24,7 +24,7 @@ impl Undefined {
/// Initialize the `undefined` property on the global object.
#[inline]
pub(crate) fn init(_: &Value) -> (&str, Value) {
pub(crate) fn init(_interpreter: &mut Interpreter) -> (&'static str, Value) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, Value::undefined())

2
boa/src/builtins/value/mod.rs

@ -214,7 +214,7 @@ impl Value {
new_obj
}
JSONValue::Object(obj) => {
let new_obj = Value::new_object(Some(&interpreter.realm.global_obj));
let new_obj = Value::new_object(Some(interpreter.global()));
for (key, json) in obj.into_iter() {
let value = Self::from_json(json, interpreter);
new_obj.set_property(

24
boa/src/exec/mod.rs

@ -23,6 +23,7 @@ mod throw;
mod try_node;
use crate::{
builtins,
builtins::{
function::{Function as FunctionObject, FunctionBody, ThisMode},
number::{f64_to_int32, f64_to_uint32},
@ -79,12 +80,25 @@ pub struct Interpreter {
impl Interpreter {
/// Creates a new interpreter.
pub fn new(realm: Realm) -> Self {
Self {
let mut interpreter = Self {
state: InterpreterState::Executing,
realm,
symbol_count: 0,
console: Console::default(),
}
};
// Add new builtIns to Interpreter Realm
// At a later date this can be removed from here and called explicitly, but for now we almost always want these default builtins
interpreter.create_intrinsics();
interpreter
}
/// Sets up the default global objects within Global
fn create_intrinsics(&mut self) {
let _timer = BoaProfiler::global().start_event("create_intrinsics", "interpreter");
// Create intrinsics, add global objects here
builtins::init(self);
}
/// Retrieves the `Realm` of this executor.
@ -99,6 +113,12 @@ impl Interpreter {
&mut self.realm
}
/// Retrieves the global object of the `Realm` of this executor.
#[inline]
pub(crate) fn global(&self) -> &Value {
&self.realm.global_obj
}
/// Generates a new `Symbol` internal hash.
///
/// This currently is an incremented value.

19
boa/src/realm.rs

@ -6,7 +6,6 @@
use crate::{
builtins::{
self,
function::{Function, NativeFunctionData},
value::Value,
},
@ -40,25 +39,11 @@ impl Realm {
// We need to clone the global here because its referenced from separate places (only pointer is cloned)
let global_env = new_global_environment(global.clone(), global.clone());
let new_realm = Self {
Self {
global_obj: global.clone(),
global_env,
environment: LexicalEnvironment::new(global),
};
// Add new builtIns to Realm
// At a later date this can be removed from here and called explicity, but for now we almost always want these default builtins
new_realm.create_instrinsics();
new_realm
}
// Sets up the default global objects within Global
fn create_instrinsics(&self) {
let _timer = BoaProfiler::global().start_event("create_instrinsics", "realm");
let global = &self.global_obj;
// Create intrinsics, add global objects here
builtins::init(global);
}
}
/// Utility to add a function to the global object

Loading…
Cancel
Save