diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index 6ca033c0e0..56988e9e79 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -48,6 +48,19 @@ Interpreter::Interpreter() : m_heap(*this) , m_console(*this) { + m_well_known_symbol_map.set("iterator", js_symbol(*this, "Symbol.iterator", false)); + m_well_known_symbol_map.set("asyncIterator", js_symbol(*this, "Symbol.asyncIterator", false)); + m_well_known_symbol_map.set("match", js_symbol(*this, "Symbol.match", false)); + m_well_known_symbol_map.set("matchAll", js_symbol(*this, "Symbol.matchAll", false)); + m_well_known_symbol_map.set("replace", js_symbol(*this, "Symbol.replace", false)); + m_well_known_symbol_map.set("search", js_symbol(*this, "Symbol.search", false)); + m_well_known_symbol_map.set("split", js_symbol(*this, "Symbol.split", false)); + m_well_known_symbol_map.set("hasInstance", js_symbol(*this, "Symbol.hasInstance", false)); + m_well_known_symbol_map.set("isConcatSpreadable", js_symbol(*this, "Symbol.isConcatSpreadable", false)); + m_well_known_symbol_map.set("unscopables", js_symbol(*this, "Symbol.unscopables", false)); + m_well_known_symbol_map.set("species", js_symbol(*this, "Symbol.species", false)); + m_well_known_symbol_map.set("toPrimitive", js_symbol(*this, "Symbol.toPrimitive", false)); + m_well_known_symbol_map.set("toStringTag", js_symbol(*this, "Symbol.toStringTag", false)); } Interpreter::~Interpreter() @@ -201,6 +214,23 @@ Reference Interpreter::get_reference(const FlyString& name) return { Reference::GlobalVariable, name }; } +Symbol* Interpreter::get_global_symbol(const String& description) +{ + auto result = m_global_symbol_map.get(description); + if (result.has_value()) + return result.value(); + + auto new_global_symbol = js_symbol(*this, description, true); + m_global_symbol_map.set(description, new_global_symbol); + return new_global_symbol; +} + +Symbol* Interpreter::get_well_known_symbol(const String& description) const +{ + ASSERT(m_well_known_symbol_map.contains(description)); + return m_well_known_symbol_map.get(description).value(); +} + void Interpreter::gather_roots(Badge, HashTable& roots) { roots.set(m_global_object); @@ -219,7 +249,11 @@ void Interpreter::gather_roots(Badge, HashTable& roots) roots.set(call_frame.environment); } - SymbolObject::gather_symbol_roots(roots); + for (auto& symbol : m_well_known_symbol_map) + roots.set(symbol.value); + + for (auto& symbol : m_global_symbol_map) + roots.set(symbol.value); } Value Interpreter::call(Function& function, Value this_value, Optional arguments) diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index 950b40aa3b..442759af30 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -111,6 +111,10 @@ public: Reference get_reference(const FlyString& name); + Symbol* get_global_symbol(const String& description); + Symbol* get_well_known_symbol(const String& description) const; + const HashMap& get_well_known_symbol_map(Badge) const { return m_well_known_symbol_map; }; + void gather_roots(Badge, HashTable&); void enter_scope(const ScopeNode&, ArgumentVector, ScopeType, GlobalObject&); @@ -217,6 +221,9 @@ private: Object* m_global_object { nullptr }; + HashMap m_well_known_symbol_map; + HashMap m_global_symbol_map; + Exception* m_exception { nullptr }; ScopeType m_unwind_until { ScopeType::None }; diff --git a/Libraries/LibJS/Runtime/Symbol.h b/Libraries/LibJS/Runtime/Symbol.h index 3f911e2b4f..22218f7dcc 100644 --- a/Libraries/LibJS/Runtime/Symbol.h +++ b/Libraries/LibJS/Runtime/Symbol.h @@ -32,6 +32,9 @@ namespace JS { class Symbol final : public Cell { + AK_MAKE_NONCOPYABLE(Symbol) + AK_MAKE_NONMOVABLE(Symbol) + public: Symbol(String, bool); virtual ~Symbol(); diff --git a/Libraries/LibJS/Runtime/SymbolConstructor.cpp b/Libraries/LibJS/Runtime/SymbolConstructor.cpp index 0e051128e2..ec540cceef 100644 --- a/Libraries/LibJS/Runtime/SymbolConstructor.cpp +++ b/Libraries/LibJS/Runtime/SymbolConstructor.cpp @@ -46,21 +46,8 @@ void SymbolConstructor::initialize(Interpreter& interpreter, GlobalObject& globa define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable); define_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable); - SymbolObject::initialize_well_known_symbols(interpreter); - - define_property("iterator", SymbolObject::well_known_iterator(), 0); - define_property("asyncIterator", SymbolObject::well_known_async_terator(), 0); - define_property("match", SymbolObject::well_known_match(), 0); - define_property("matchAll", SymbolObject::well_known_match_all(), 0); - define_property("replace", SymbolObject::well_known_replace(), 0); - define_property("search", SymbolObject::well_known_search(), 0); - define_property("split", SymbolObject::well_known_split(), 0); - define_property("hasInstance", SymbolObject::well_known_has_instance(), 0); - define_property("isConcatSpreadable", SymbolObject::well_known_is_concat_spreadable(), 0); - define_property("unscopables", SymbolObject::well_known_unscopables(), 0); - define_property("species", SymbolObject::well_known_species(), 0); - define_property("toPrimitive", SymbolObject::well_known_to_primtive(), 0); - define_property("toStringTag", SymbolObject::well_known_to_string_tag(), 0); + for (auto& entry : interpreter.get_well_known_symbol_map({})) + define_property(entry.key, entry.value, 0); } SymbolConstructor::~SymbolConstructor() @@ -89,7 +76,7 @@ JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_) description = interpreter.argument(0).to_string(interpreter); } - return SymbolObject::get_global(interpreter, description); + return interpreter.get_global_symbol(description); } JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::key_for) diff --git a/Libraries/LibJS/Runtime/SymbolObject.cpp b/Libraries/LibJS/Runtime/SymbolObject.cpp index 873a4d1b38..f04f1fdee6 100644 --- a/Libraries/LibJS/Runtime/SymbolObject.cpp +++ b/Libraries/LibJS/Runtime/SymbolObject.cpp @@ -34,21 +34,6 @@ namespace JS { -HashMap SymbolObject::s_global_symbol_map; - -Value SymbolObject::s_well_known_iterator; -Value SymbolObject::s_well_known_async_terator; -Value SymbolObject::s_well_known_match; -Value SymbolObject::s_well_known_match_all; -Value SymbolObject::s_well_known_replace; -Value SymbolObject::s_well_known_search; -Value SymbolObject::s_well_known_split; -Value SymbolObject::s_well_known_has_instance; -Value SymbolObject::s_well_known_is_concat_spreadable; -Value SymbolObject::s_well_known_unscopables; -Value SymbolObject::s_well_known_species; -Value SymbolObject::s_well_known_to_primtive; -Value SymbolObject::s_well_known_to_string_tag; SymbolObject* SymbolObject::create(GlobalObject& global_object, Symbol& primitive_symbol) { @@ -65,54 +50,6 @@ SymbolObject::~SymbolObject() { } -Value SymbolObject::get_global(Interpreter& interpreter, String description) -{ - auto global_symbol = s_global_symbol_map.get(description); - if (global_symbol.has_value()) - return global_symbol.value(); - - auto symbol = js_symbol(interpreter, description, true); - s_global_symbol_map.set(description, symbol); - return Value(symbol); -} - -void SymbolObject::initialize_well_known_symbols(Interpreter& interpreter) -{ - SymbolObject::s_well_known_iterator = Value(js_symbol(interpreter, "Symbol.iterator", false)); - SymbolObject::s_well_known_async_terator = Value(js_symbol(interpreter, "Symbol.asyncIterator", false)); - SymbolObject::s_well_known_match = Value(js_symbol(interpreter, "Symbol.match", false)); - SymbolObject::s_well_known_match_all = Value(js_symbol(interpreter, "Symbol.matchAll", false)); - SymbolObject::s_well_known_replace = Value(js_symbol(interpreter, "Symbol.replace", false)); - SymbolObject::s_well_known_search = Value(js_symbol(interpreter, "Symbol.search", false)); - SymbolObject::s_well_known_split = Value(js_symbol(interpreter, "Symbol.split", false)); - SymbolObject::s_well_known_has_instance = Value(js_symbol(interpreter, "Symbol.hasInstance", false)); - SymbolObject::s_well_known_is_concat_spreadable = Value(js_symbol(interpreter, "Symbol.isConcatSpreadable", false)); - SymbolObject::s_well_known_unscopables = Value(js_symbol(interpreter, "Symbol.unscopables", false)); - SymbolObject::s_well_known_species = Value(js_symbol(interpreter, "Symbol.species", false)); - SymbolObject::s_well_known_to_primtive = Value(js_symbol(interpreter, "Symbol.toPrimitive", false)); - SymbolObject::s_well_known_to_string_tag = Value(js_symbol(interpreter, "Symbol.toStringTag", false)); -} - -void SymbolObject::gather_symbol_roots(HashTable& roots) -{ - for (auto& global_symbol : s_global_symbol_map) - roots.set(&global_symbol.value.as_symbol()); - - roots.set(&s_well_known_iterator.as_symbol()); - roots.set(&s_well_known_async_terator.as_symbol()); - roots.set(&s_well_known_match.as_symbol()); - roots.set(&s_well_known_match_all.as_symbol()); - roots.set(&s_well_known_replace.as_symbol()); - roots.set(&s_well_known_search.as_symbol()); - roots.set(&s_well_known_split.as_symbol()); - roots.set(&s_well_known_has_instance.as_symbol()); - roots.set(&s_well_known_is_concat_spreadable.as_symbol()); - roots.set(&s_well_known_unscopables.as_symbol()); - roots.set(&s_well_known_species.as_symbol()); - roots.set(&s_well_known_to_primtive.as_symbol()); - roots.set(&s_well_known_to_string_tag.as_symbol()); -} - void SymbolObject::visit_children(Cell::Visitor& visitor) { Object::visit_children(visitor); diff --git a/Libraries/LibJS/Runtime/SymbolObject.h b/Libraries/LibJS/Runtime/SymbolObject.h index 763354b233..31e5a3e87e 100644 --- a/Libraries/LibJS/Runtime/SymbolObject.h +++ b/Libraries/LibJS/Runtime/SymbolObject.h @@ -46,51 +46,16 @@ public: const String& description() const { return m_symbol.description(); } bool is_global() const { return m_symbol.is_global(); } - static Value get_global(Interpreter&, String description); - virtual Value value_of() const override { return Value(&m_symbol); } - static void initialize_well_known_symbols(Interpreter&); - static void gather_symbol_roots(HashTable& roots); - - static Value well_known_iterator() { return s_well_known_iterator; }; - static Value well_known_async_terator() { return s_well_known_async_terator; }; - static Value well_known_match() { return s_well_known_match; }; - static Value well_known_match_all() { return s_well_known_match_all; }; - static Value well_known_replace() { return s_well_known_replace; }; - static Value well_known_search() { return s_well_known_search; }; - static Value well_known_split() { return s_well_known_split; }; - static Value well_known_has_instance() { return s_well_known_has_instance; }; - static Value well_known_is_concat_spreadable() { return s_well_known_is_concat_spreadable; }; - static Value well_known_unscopables() { return s_well_known_unscopables; }; - static Value well_known_species() { return s_well_known_species; }; - static Value well_known_to_primtive() { return s_well_known_to_primtive; }; - static Value well_known_to_string_tag() { return s_well_known_to_string_tag; }; - private: virtual void visit_children(Visitor&) override; virtual bool is_symbol_object() const override { return true; } Symbol& m_symbol; - - static HashMap s_global_symbol_map; - - static Value s_well_known_iterator; - static Value s_well_known_async_terator; - static Value s_well_known_match; - static Value s_well_known_match_all; - static Value s_well_known_replace; - static Value s_well_known_search; - static Value s_well_known_split; - static Value s_well_known_has_instance; - static Value s_well_known_is_concat_spreadable; - static Value s_well_known_unscopables; - static Value s_well_known_species; - static Value s_well_known_to_primtive; - static Value s_well_known_to_string_tag; }; }