diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index 2a9ab4fb16..abb5512ec2 100644 --- a/boa/src/builtins/array/mod.rs +++ b/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 diff --git a/boa/src/builtins/bigint/mod.rs b/boa/src/builtins/bigint/mod.rs index 01f0ade220..aac4b68ff4 100644 --- a/boa/src/builtins/bigint/mod.rs +++ b/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)); diff --git a/boa/src/builtins/boolean/mod.rs b/boa/src/builtins/boolean/mod.rs index 6edad1e281..1698f33c16 100644 --- a/boa/src/builtins/boolean/mod.rs +++ b/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 diff --git a/boa/src/builtins/console/mod.rs b/boa/src/builtins/console/mod.rs index 68ff83c47f..c362e6a6fa 100644 --- a/boa/src/builtins/console/mod.rs +++ b/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)); diff --git a/boa/src/builtins/error/mod.rs b/boa/src/builtins/error/mod.rs index 828ab554ce..99fc5f7af0 100644 --- a/boa/src/builtins/error/mod.rs +++ b/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)); diff --git a/boa/src/builtins/error/range.rs b/boa/src/builtins/error/range.rs index 91d1f1a1c1..d4b2ea778f 100644 --- a/boa/src/builtins/error/range.rs +++ b/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)); diff --git a/boa/src/builtins/error/reference.rs b/boa/src/builtins/error/reference.rs index b757fcccbe..1636beec4b 100644 --- a/boa/src/builtins/error/reference.rs +++ b/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)); diff --git a/boa/src/builtins/error/syntax.rs b/boa/src/builtins/error/syntax.rs index 783551651a..07b4497f29 100644 --- a/boa/src/builtins/error/syntax.rs +++ b/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)); diff --git a/boa/src/builtins/error/type.rs b/boa/src/builtins/error/type.rs index 0fef65222f..63bec5122b 100644 --- a/boa/src/builtins/error/type.rs +++ b/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)); diff --git a/boa/src/builtins/function/mod.rs b/boa/src/builtins/function/mod.rs index cb885bc737..491c2ef0b6 100644 --- a/boa/src/builtins/function/mod.rs +++ b/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)); diff --git a/boa/src/builtins/global_this/mod.rs b/boa/src/builtins/global_this/mod.rs index 2ef49347b9..481b619dec 100644 --- a/boa/src/builtins/global_this/mod.rs +++ b/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()) diff --git a/boa/src/builtins/infinity/mod.rs b/boa/src/builtins/infinity/mod.rs index 55e0347cf7..7cb9b78fff 100644 --- a/boa/src/builtins/infinity/mod.rs +++ b/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)) diff --git a/boa/src/builtins/json/mod.rs b/boa/src/builtins/json/mod.rs index e01c46f9e3..adc570fefd 100644 --- a/boa/src/builtins/json/mod.rs +++ b/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)); diff --git a/boa/src/builtins/map/mod.rs b/boa/src/builtins/map/mod.rs index cad09ee98e..0de4d53619 100644 --- a/boa/src/builtins/map/mod.rs +++ b/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 diff --git a/boa/src/builtins/math/mod.rs b/boa/src/builtins/math/mod.rs index 02bd617744..49189cb1f4 100644 --- a/boa/src/builtins/math/mod.rs +++ b/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)) diff --git a/boa/src/builtins/mod.rs b/boa/src/builtins/mod.rs index 127426153a..91449bb704 100644 --- a/boa/src/builtins/mod.rs +++ b/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"), } } diff --git a/boa/src/builtins/nan/mod.rs b/boa/src/builtins/nan/mod.rs index a87e17c403..eeb29c039c 100644 --- a/boa/src/builtins/nan/mod.rs +++ b/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)) diff --git a/boa/src/builtins/number/mod.rs b/boa/src/builtins/number/mod.rs index 332f84c9d3..fa738d75c0 100644 --- a/boa/src/builtins/number/mod.rs +++ b/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)); diff --git a/boa/src/builtins/object/mod.rs b/boa/src/builtins/object/mod.rs index 2cd9073cb0..26c533f923 100644 --- a/boa/src/builtins/object/mod.rs +++ b/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); diff --git a/boa/src/builtins/regexp/mod.rs b/boa/src/builtins/regexp/mod.rs index cf96bfb96e..4e6f2b9eda 100644 --- a/boa/src/builtins/regexp/mod.rs +++ b/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)) diff --git a/boa/src/builtins/string/mod.rs b/boa/src/builtins/string/mod.rs index 5bad6de4b0..b7dbf7643e 100644 --- a/boa/src/builtins/string/mod.rs +++ b/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` diff --git a/boa/src/builtins/symbol/mod.rs b/boa/src/builtins/symbol/mod.rs index 6548963db8..3498970fec 100644 --- a/boa/src/builtins/symbol/mod.rs +++ b/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) } } diff --git a/boa/src/builtins/undefined/mod.rs b/boa/src/builtins/undefined/mod.rs index 922c284c63..ae21964a3a 100644 --- a/boa/src/builtins/undefined/mod.rs +++ b/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()) diff --git a/boa/src/builtins/value/mod.rs b/boa/src/builtins/value/mod.rs index 6f05364c22..27ebde5a7c 100644 --- a/boa/src/builtins/value/mod.rs +++ b/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( diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index 5d2cc1b292..c33117cb74 100644 --- a/boa/src/exec/mod.rs +++ b/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. diff --git a/boa/src/realm.rs b/boa/src/realm.rs index f7df95a5a6..5147be86ff 100644 --- a/boa/src/realm.rs +++ b/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