mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 21:22:46 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									2ea85355fe
								
							
						
					
					
						commit
						c485c86015
					
				
					 7 changed files with 42 additions and 31 deletions
				
			
		|  | @ -75,6 +75,21 @@ | ||||||
|     JS_ENUMERATE_NATIVE_OBJECTS    \ |     JS_ENUMERATE_NATIVE_OBJECTS    \ | ||||||
|     JS_ENUMERATE_ERROR_SUBCLASSES |     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 { | namespace JS { | ||||||
| 
 | 
 | ||||||
| class ASTNode; | class ASTNode; | ||||||
|  |  | ||||||
|  | @ -48,19 +48,10 @@ Interpreter::Interpreter() | ||||||
|     : m_heap(*this) |     : m_heap(*this) | ||||||
|     , m_console(*this) |     , m_console(*this) | ||||||
| { | { | ||||||
|     m_well_known_symbol_map.set("iterator", js_symbol(*this, "Symbol.iterator", false)); | #define __JS_ENUMERATE(SymbolName, snake_name) \ | ||||||
|     m_well_known_symbol_map.set("asyncIterator", js_symbol(*this, "Symbol.asyncIterator", false)); |     m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false); | ||||||
|     m_well_known_symbol_map.set("match", js_symbol(*this, "Symbol.match", false)); |     JS_ENUMERATE_WELL_KNOWN_SYMBOLS | ||||||
|     m_well_known_symbol_map.set("matchAll", js_symbol(*this, "Symbol.matchAll", false)); | #undef __JS_ENUMERATE | ||||||
|     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() | Interpreter::~Interpreter() | ||||||
|  | @ -225,12 +216,6 @@ Symbol* Interpreter::get_global_symbol(const String& description) | ||||||
|     return 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<Heap>, HashTable<Cell*>& roots) | void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots) | ||||||
| { | { | ||||||
|     roots.set(m_global_object); |     roots.set(m_global_object); | ||||||
|  | @ -249,8 +234,10 @@ void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots) | ||||||
|         roots.set(call_frame.environment); |         roots.set(call_frame.environment); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (auto& symbol : m_well_known_symbol_map) | #define __JS_ENUMERATE(SymbolName, snake_name) \ | ||||||
|         roots.set(symbol.value); |     roots.set(well_known_symbol_##snake_name()); | ||||||
|  |     JS_ENUMERATE_WELL_KNOWN_SYMBOLS | ||||||
|  | #undef __JS_ENUMERATE | ||||||
| 
 | 
 | ||||||
|     for (auto& symbol : m_global_symbol_map) |     for (auto& symbol : m_global_symbol_map) | ||||||
|         roots.set(symbol.value); |         roots.set(symbol.value); | ||||||
|  |  | ||||||
|  | @ -112,8 +112,6 @@ public: | ||||||
|     Reference get_reference(const FlyString& name); |     Reference get_reference(const FlyString& name); | ||||||
| 
 | 
 | ||||||
|     Symbol* get_global_symbol(const String& description); |     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*>&); |     void gather_roots(Badge<Heap>, HashTable<Cell*>&); | ||||||
| 
 | 
 | ||||||
|  | @ -209,6 +207,11 @@ public: | ||||||
|     const LexicalEnvironment* get_this_environment() const; |     const LexicalEnvironment* get_this_environment() const; | ||||||
|     Value get_new_target() 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: | private: | ||||||
|     Interpreter(); |     Interpreter(); | ||||||
| 
 | 
 | ||||||
|  | @ -221,9 +224,6 @@ private: | ||||||
| 
 | 
 | ||||||
|     Object* m_global_object { nullptr }; |     Object* m_global_object { nullptr }; | ||||||
| 
 | 
 | ||||||
|     HashMap<String, Symbol*> m_well_known_symbol_map; |  | ||||||
|     HashMap<String, Symbol*> m_global_symbol_map; |  | ||||||
| 
 |  | ||||||
|     Exception* m_exception { nullptr }; |     Exception* m_exception { nullptr }; | ||||||
| 
 | 
 | ||||||
|     ScopeType m_unwind_until { ScopeType::None }; |     ScopeType m_unwind_until { ScopeType::None }; | ||||||
|  | @ -232,6 +232,13 @@ private: | ||||||
|     bool m_underscore_is_last_value { false }; |     bool m_underscore_is_last_value { false }; | ||||||
| 
 | 
 | ||||||
|     Console m_console; |     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 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -81,7 +81,7 @@ void ArrayPrototype::initialize(Interpreter& interpreter, GlobalObject& global_o | ||||||
|     // Use define_property here instead of define_native_function so that
 |     // Use define_property here instead of define_native_function so that
 | ||||||
|     // Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
 |     // Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
 | ||||||
|     // evaluates to true
 |     // 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() | ArrayPrototype::~ArrayPrototype() | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ Object* get_iterator(Object& obj, String hint, Value method) | ||||||
|     if (method.is_empty()) { |     if (method.is_empty()) { | ||||||
|         if (hint == "async") |         if (hint == "async") | ||||||
|             TODO(); |             TODO(); | ||||||
|         method = obj.get(obj.interpreter().get_well_known_symbol("iterator")); |         method = obj.get(obj.interpreter().well_known_symbol_iterator()); | ||||||
|         if (interpreter.exception()) |         if (interpreter.exception()) | ||||||
|             return {}; |             return {}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ IteratorPrototype::IteratorPrototype(GlobalObject& global_object) | ||||||
| void IteratorPrototype::initialize(Interpreter& interpreter, GlobalObject& global_object) | void IteratorPrototype::initialize(Interpreter& interpreter, GlobalObject& global_object) | ||||||
| { | { | ||||||
|     Object::initialize(interpreter, 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() | IteratorPrototype::~IteratorPrototype() | ||||||
|  |  | ||||||
|  | @ -46,8 +46,10 @@ void SymbolConstructor::initialize(Interpreter& interpreter, GlobalObject& globa | ||||||
|     define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable); |     define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable); | ||||||
|     define_native_function("keyFor", key_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 __JS_ENUMERATE(SymbolName, snake_name) \ | ||||||
|         define_property(entry.key, entry.value, 0); |     define_property(#SymbolName, interpreter.well_known_symbol_##snake_name(), 0); | ||||||
|  |     JS_ENUMERATE_WELL_KNOWN_SYMBOLS | ||||||
|  | #undef __JS_ENUMERATE | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SymbolConstructor::~SymbolConstructor() | SymbolConstructor::~SymbolConstructor() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Matthew Olsson
						Matthew Olsson