From fa9228684fc3c7783a2c4b7aa902212adecc1e92 Mon Sep 17 00:00:00 2001 From: joshwd36 Date: Wed, 22 Jul 2020 03:32:44 +0100 Subject: [PATCH] Move create_intrinsics to Interpreter and implement Well-Known Symbols --- boa/src/builtins/array/mod.rs | 3 +- boa/src/builtins/bigint/mod.rs | 3 +- boa/src/builtins/boolean/mod.rs | 3 +- boa/src/builtins/console/mod.rs | 3 +- boa/src/builtins/error/mod.rs | 3 +- boa/src/builtins/error/range.rs | 3 +- boa/src/builtins/error/reference.rs | 3 +- boa/src/builtins/error/syntax.rs | 3 +- boa/src/builtins/error/type.rs | 3 +- boa/src/builtins/function/mod.rs | 3 +- boa/src/builtins/global_this/mod.rs | 5 +-- boa/src/builtins/infinity/mod.rs | 4 +-- boa/src/builtins/json/mod.rs | 3 +- boa/src/builtins/map/mod.rs | 3 +- boa/src/builtins/math/mod.rs | 3 +- boa/src/builtins/mod.rs | 15 +++++---- boa/src/builtins/nan/mod.rs | 4 +-- boa/src/builtins/number/mod.rs | 3 +- boa/src/builtins/object/mod.rs | 3 +- boa/src/builtins/regexp/mod.rs | 3 +- boa/src/builtins/string/mod.rs | 3 +- boa/src/builtins/symbol/mod.rs | 52 ++++++++++++++++++++++++++++- boa/src/builtins/undefined/mod.rs | 4 +-- boa/src/exec/mod.rs | 18 ++++++++-- boa/src/realm.rs | 19 ++--------- 25 files changed, 121 insertions(+), 51 deletions(-) diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index 294cc31859..ede7a2cebc 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..6e97a1ed70 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..4dc08e2d92 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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 7b7c68c783..dbd1da6aa6 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..b3c20cabb4 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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 ba8e76574c..76c30bd5ee 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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 842bebf1a8..e23a2f079e 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..dbafff7386 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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 27d3dbbf46..5e3e0ba864 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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 d2d53395de..c768b7102a 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..dd04e6f6a6 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..8f3535a5ff 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) -> (&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 75ab63a430..6cd91806d5 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..2ec6a1eaf7 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..dee0367b85 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..7ef9e49513 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,15 @@ 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 name = name.to_string(); + let global = &interpreter.realm.global_obj; + 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..b4cdd4665a 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) -> (&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..99a510c22a 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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 ea614a6666..a4e60ee8ef 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..8e1dfedb1c 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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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 c657691751..282e687c61 100644 --- a/boa/src/builtins/string/mod.rs +++ b/boa/src/builtins/string/mod.rs @@ -1023,7 +1023,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) -> (&str, Value) { + let global = &interpreter.realm.global_obj; 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..51d6e39dbf 100644 --- a/boa/src/builtins/symbol/mod.rs +++ b/boa/src/builtins/symbol/mod.rs @@ -100,7 +100,40 @@ impl Symbol { /// Initialise the `Symbol` object on the global object. #[inline] - pub fn init(global: &Value) -> (&str, Value) { + pub fn init(interpreter: &mut Interpreter) -> (&str, Value) { + 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.realm.global_obj; let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); // Create prototype object @@ -118,6 +151,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..ec1ad280cb 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) -> (&str, Value) { let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); (Self::NAME, Value::undefined()) diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index 29fba39608..df53f1abbe 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. diff --git a/boa/src/realm.rs b/boa/src/realm.rs index 1119ef7bca..5e4bfe0ceb 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