Ver código fonte

LibJS: Use macros to enumerate well-known symbols

Not only is this a much nicer api (can't pass a typo'd string into the
get_well_known_symbol function), it is also a bit more performant since
there are no hashmap lookups.
Matthew Olsson 5 anos atrás
pai
commit
c485c86015

+ 15 - 0
Libraries/LibJS/Forward.h

@@ -75,6 +75,21 @@
     JS_ENUMERATE_NATIVE_OBJECTS    \
     JS_ENUMERATE_ERROR_SUBCLASSES
 
+#define JS_ENUMERATE_WELL_KNOWN_SYMBOLS                        \
+    __JS_ENUMERATE(iterator, iterator)                         \
+    __JS_ENUMERATE(asyncIterator, async_iterator)              \
+    __JS_ENUMERATE(match, match)                               \
+    __JS_ENUMERATE(matchAll, match_all)                        \
+    __JS_ENUMERATE(replace, replace)                           \
+    __JS_ENUMERATE(search, search)                             \
+    __JS_ENUMERATE(split, split)                               \
+    __JS_ENUMERATE(hasInstance, has_instance)                  \
+    __JS_ENUMERATE(isConcatSpreadable, is_concat_spreadable)   \
+    __JS_ENUMERATE(unscopables, unscopables)                   \
+    __JS_ENUMERATE(species, species)                           \
+    __JS_ENUMERATE(toPrimitive, to_primitive)                  \
+    __JS_ENUMERATE(toStringTag, to_string_tag)
+
 namespace JS {
 
 class ASTNode;

+ 8 - 21
Libraries/LibJS/Interpreter.cpp

@@ -48,19 +48,10 @@ 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));
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
 }
 
 Interpreter::~Interpreter()
@@ -225,12 +216,6 @@ Symbol* Interpreter::get_global_symbol(const String& description)
     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<Heap>, HashTable<Cell*>& roots)
 {
     roots.set(m_global_object);
@@ -249,8 +234,10 @@ void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots)
         roots.set(call_frame.environment);
     }
 
-    for (auto& symbol : m_well_known_symbol_map)
-        roots.set(symbol.value);
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    roots.set(well_known_symbol_##snake_name());
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
 
     for (auto& symbol : m_global_symbol_map)
         roots.set(symbol.value);

+ 12 - 5
Libraries/LibJS/Interpreter.h

@@ -112,8 +112,6 @@ 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<String, Symbol*>& get_well_known_symbol_map(Badge<SymbolConstructor>) const { return m_well_known_symbol_map; };
 
     void gather_roots(Badge<Heap>, HashTable<Cell*>&);
 
@@ -209,6 +207,11 @@ public:
     const LexicalEnvironment* get_this_environment() const;
     Value get_new_target() const;
 
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    Symbol* well_known_symbol_##snake_name() const { return m_well_known_symbol_##snake_name; }
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
+
 private:
     Interpreter();
 
@@ -221,9 +224,6 @@ private:
 
     Object* m_global_object { nullptr };
 
-    HashMap<String, Symbol*> m_well_known_symbol_map;
-    HashMap<String, Symbol*> m_global_symbol_map;
-
     Exception* m_exception { nullptr };
 
     ScopeType m_unwind_until { ScopeType::None };
@@ -232,6 +232,13 @@ private:
     bool m_underscore_is_last_value { false };
 
     Console m_console;
+
+    HashMap<String, Symbol*> m_global_symbol_map;
+
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    Symbol* m_well_known_symbol_##snake_name { nullptr };
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
 };
 
 }

+ 1 - 1
Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -81,7 +81,7 @@ void ArrayPrototype::initialize(Interpreter& interpreter, GlobalObject& global_o
     // Use define_property here instead of define_native_function so that
     // Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
     // evaluates to true
-    define_property(interpreter.get_well_known_symbol("iterator"), get("values"), attr);
+    define_property(interpreter.well_known_symbol_iterator(), get("values"), attr);
 }
 
 ArrayPrototype::~ArrayPrototype()

+ 1 - 1
Libraries/LibJS/Runtime/IteratorOperations.cpp

@@ -36,7 +36,7 @@ Object* get_iterator(Object& obj, String hint, Value method)
     if (method.is_empty()) {
         if (hint == "async")
             TODO();
-        method = obj.get(obj.interpreter().get_well_known_symbol("iterator"));
+        method = obj.get(obj.interpreter().well_known_symbol_iterator());
         if (interpreter.exception())
             return {};
     }

+ 1 - 1
Libraries/LibJS/Runtime/IteratorPrototype.cpp

@@ -37,7 +37,7 @@ IteratorPrototype::IteratorPrototype(GlobalObject& global_object)
 void IteratorPrototype::initialize(Interpreter& interpreter, GlobalObject& global_object)
 {
     Object::initialize(interpreter, global_object);
-    define_native_function(interpreter.get_well_known_symbol("iterator"), symbol_iterator, 0, Attribute::Writable | Attribute::Enumerable);
+    define_native_function(interpreter.well_known_symbol_iterator(), symbol_iterator, 0, Attribute::Writable | Attribute::Enumerable);
 }
 
 IteratorPrototype::~IteratorPrototype()

+ 4 - 2
Libraries/LibJS/Runtime/SymbolConstructor.cpp

@@ -46,8 +46,10 @@ 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);
 
-    for (auto& entry : interpreter.get_well_known_symbol_map({}))
-        define_property(entry.key, entry.value, 0);
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    define_property(#SymbolName, interpreter.well_known_symbol_##snake_name(), 0);
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
 }
 
 SymbolConstructor::~SymbolConstructor()