mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 12:32:43 +00:00 
			
		
		
		
	LibJS: Add argument(i) and argument_count() to Interpreter
Add some convenience accessors for retrieving arguments from the current call frame.
This commit is contained in:
		
							parent
							
								
									1549c5c48b
								
							
						
					
					
						commit
						cd1d369cdd
					
				
					 9 changed files with 49 additions and 34 deletions
				
			
		|  | @ -107,6 +107,21 @@ public: | ||||||
|     void pop_call_frame() { m_call_stack.take_last(); } |     void pop_call_frame() { m_call_stack.take_last(); } | ||||||
|     const CallFrame& call_frame() { return m_call_stack.last(); } |     const CallFrame& call_frame() { return m_call_stack.last(); } | ||||||
| 
 | 
 | ||||||
|  |     size_t argument_count() const | ||||||
|  |     { | ||||||
|  |         if (m_call_stack.is_empty()) | ||||||
|  |             return 0; | ||||||
|  |         return m_call_stack.last().arguments.size(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Value argument(size_t index) const | ||||||
|  |     { | ||||||
|  |         if (m_call_stack.is_empty()) | ||||||
|  |             return {}; | ||||||
|  |         auto& arguments = m_call_stack.last().arguments; | ||||||
|  |         return index < arguments.size() ? arguments[index] : js_undefined(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     Value this_value() const |     Value this_value() const | ||||||
|     { |     { | ||||||
|         if (m_call_stack.is_empty()) |         if (m_call_stack.is_empty()) | ||||||
|  |  | ||||||
|  | @ -50,9 +50,9 @@ Value ArrayPrototype::push(Interpreter& interpreter) | ||||||
|     if (!this_object) |     if (!this_object) | ||||||
|         return {}; |         return {}; | ||||||
|     ASSERT(this_object->is_array()); |     ASSERT(this_object->is_array()); | ||||||
|     if (interpreter.call_frame().arguments.is_empty()) |     if (!interpreter.argument_count()) | ||||||
|         return js_undefined(); |         return js_undefined(); | ||||||
|     static_cast<Array*>(this_object)->push(interpreter.call_frame().arguments[0]); |     static_cast<Array*>(this_object)->push(interpreter.argument(0)); | ||||||
|     return Value(static_cast<const Array*>(this_object)->length()); |     return Value(static_cast<const Array*>(this_object)->length()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -43,9 +43,9 @@ ConsoleObject::~ConsoleObject() | ||||||
| 
 | 
 | ||||||
| Value ConsoleObject::log(Interpreter& interpreter) | Value ConsoleObject::log(Interpreter& interpreter) | ||||||
| { | { | ||||||
|     for (size_t i = 0; i < interpreter.call_frame().arguments.size(); ++i) { |     for (size_t i = 0; i < interpreter.argument_count(); ++i) { | ||||||
|         printf("%s", interpreter.call_frame().arguments[i].to_string().characters()); |         printf("%s", interpreter.argument(i).to_string().characters()); | ||||||
|         if (i != interpreter.call_frame().arguments.size() - 1) |         if (i != interpreter.argument_count() - 1) | ||||||
|             putchar(' '); |             putchar(' '); | ||||||
|     } |     } | ||||||
|     putchar('\n'); |     putchar('\n'); | ||||||
|  |  | ||||||
|  | @ -39,9 +39,9 @@ Value GlobalObject::gc(Interpreter& interpreter) | ||||||
| 
 | 
 | ||||||
| Value GlobalObject::is_nan(Interpreter& interpreter) | Value GlobalObject::is_nan(Interpreter& interpreter) | ||||||
| { | { | ||||||
|     if (interpreter.call_frame().arguments.size() < 1) |     if (interpreter.argument_count() < 1) | ||||||
|         return js_undefined(); |         return js_undefined(); | ||||||
|     return Value(interpreter.call_frame().arguments[0].to_number().is_nan()); |     return Value(interpreter.argument(0).to_number().is_nan()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -53,10 +53,10 @@ MathObject::~MathObject() | ||||||
| 
 | 
 | ||||||
| Value MathObject::abs(Interpreter& interpreter) | Value MathObject::abs(Interpreter& interpreter) | ||||||
| { | { | ||||||
|     if (interpreter.call_frame().arguments.is_empty()) |     if (!interpreter.argument_count()) | ||||||
|         return js_nan(); |         return js_nan(); | ||||||
| 
 | 
 | ||||||
|     auto number = interpreter.call_frame().arguments[0].to_number(); |     auto number = interpreter.argument(0).to_number(); | ||||||
|     if (number.is_nan()) |     if (number.is_nan()) | ||||||
|         return js_nan(); |         return js_nan(); | ||||||
|     return Value(number.as_double() >= 0 ? number.as_double() : -number.as_double()); |     return Value(number.as_double() >= 0 ? number.as_double() : -number.as_double()); | ||||||
|  |  | ||||||
|  | @ -57,9 +57,9 @@ Value ObjectConstructor::construct(Interpreter& interpreter) | ||||||
| 
 | 
 | ||||||
| Value ObjectConstructor::get_own_property_names(Interpreter& interpreter) | Value ObjectConstructor::get_own_property_names(Interpreter& interpreter) | ||||||
| { | { | ||||||
|     if (interpreter.call_frame().arguments.size() < 1) |     if (!interpreter.argument_count()) | ||||||
|         return {}; |         return {}; | ||||||
|     auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap()); |     auto* object = interpreter.argument(0).to_object(interpreter.heap()); | ||||||
|     if (interpreter.exception()) |     if (interpreter.exception()) | ||||||
|         return {}; |         return {}; | ||||||
|     auto* result = interpreter.heap().allocate<Array>(); |     auto* result = interpreter.heap().allocate<Array>(); | ||||||
|  | @ -75,9 +75,9 @@ Value ObjectConstructor::get_own_property_names(Interpreter& interpreter) | ||||||
| 
 | 
 | ||||||
| Value ObjectConstructor::get_prototype_of(Interpreter& interpreter) | Value ObjectConstructor::get_prototype_of(Interpreter& interpreter) | ||||||
| { | { | ||||||
|     if (interpreter.call_frame().arguments.size() < 1) |     if (!interpreter.argument_count()) | ||||||
|         return {}; |         return {}; | ||||||
|     auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap()); |     auto* object = interpreter.argument(0).to_object(interpreter.heap()); | ||||||
|     if (interpreter.exception()) |     if (interpreter.exception()) | ||||||
|         return {}; |         return {}; | ||||||
|     return object->prototype(); |     return object->prototype(); | ||||||
|  | @ -85,14 +85,14 @@ Value ObjectConstructor::get_prototype_of(Interpreter& interpreter) | ||||||
| 
 | 
 | ||||||
| Value ObjectConstructor::set_prototype_of(Interpreter& interpreter) | Value ObjectConstructor::set_prototype_of(Interpreter& interpreter) | ||||||
| { | { | ||||||
|     if (interpreter.call_frame().arguments.size() < 2) |     if (interpreter.argument_count() < 2) | ||||||
|         return {}; |         return {}; | ||||||
|     if (!interpreter.call_frame().arguments[1].is_object()) |     if (!interpreter.argument(0).is_object()) | ||||||
|         return {}; |         return {}; | ||||||
|     auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap()); |     auto* object = interpreter.argument(0).to_object(interpreter.heap()); | ||||||
|     if (interpreter.exception()) |     if (interpreter.exception()) | ||||||
|         return {}; |         return {}; | ||||||
|     object->set_prototype(&const_cast<Object&>(interpreter.call_frame().arguments[1].as_object())); |     object->set_prototype(&const_cast<Object&>(interpreter.argument(1).as_object())); | ||||||
|     return {}; |     return {}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -51,9 +51,9 @@ Value ObjectPrototype::has_own_property(Interpreter& interpreter) | ||||||
|     auto* this_object = interpreter.this_value().to_object(interpreter.heap()); |     auto* this_object = interpreter.this_value().to_object(interpreter.heap()); | ||||||
|     if (!this_object) |     if (!this_object) | ||||||
|         return {}; |         return {}; | ||||||
|     if (interpreter.call_frame().arguments.is_empty()) |     if (!interpreter.argument_count()) | ||||||
|         return js_undefined(); |         return {}; | ||||||
|     return Value(this_object->has_own_property(interpreter.call_frame().arguments[0].to_string())); |     return Value(this_object->has_own_property(interpreter.argument(0).to_string())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Value ObjectPrototype::to_string(Interpreter& interpreter) | Value ObjectPrototype::to_string(Interpreter& interpreter) | ||||||
|  |  | ||||||
|  | @ -54,8 +54,8 @@ Value StringPrototype::char_at(Interpreter& interpreter) | ||||||
|     if (!this_object) |     if (!this_object) | ||||||
|         return {}; |         return {}; | ||||||
|     i32 index = 0; |     i32 index = 0; | ||||||
|     if (!interpreter.call_frame().arguments.is_empty()) |     if (interpreter.argument_count()) | ||||||
|         index = interpreter.call_frame().arguments[0].to_i32(); |         index = interpreter.argument(0).to_i32(); | ||||||
|     ASSERT(this_object->is_string_object()); |     ASSERT(this_object->is_string_object()); | ||||||
|     auto underlying_string = static_cast<const StringObject*>(this_object)->primitive_string()->string(); |     auto underlying_string = static_cast<const StringObject*>(this_object)->primitive_string()->string(); | ||||||
|     if (index < 0 || index >= static_cast<i32>(underlying_string.length())) |     if (index < 0 || index >= static_cast<i32>(underlying_string.length())) | ||||||
|  | @ -69,13 +69,13 @@ Value StringPrototype::repeat(Interpreter& interpreter) | ||||||
|     if (!this_object) |     if (!this_object) | ||||||
|         return {}; |         return {}; | ||||||
|     ASSERT(this_object->is_string_object()); |     ASSERT(this_object->is_string_object()); | ||||||
|     if (interpreter.call_frame().arguments.is_empty()) |     if (!interpreter.argument_count()) | ||||||
|         return js_string(interpreter.heap(), String::empty()); |         return js_string(interpreter.heap(), String::empty()); | ||||||
|     i32 count = 0; |     i32 count = 0; | ||||||
|     count = interpreter.call_frame().arguments[0].to_i32(); |     count = interpreter.argument(0).to_i32(); | ||||||
|     if (count < 0) { |     if (count < 0) { | ||||||
|         // FIXME: throw RangeError
 |         // FIXME: throw RangeError
 | ||||||
|         return js_undefined(); |         return {}; | ||||||
|     } |     } | ||||||
|     auto* string_object = static_cast<StringObject*>(this_object); |     auto* string_object = static_cast<StringObject*>(this_object); | ||||||
|     StringBuilder builder; |     StringBuilder builder; | ||||||
|  | @ -89,13 +89,13 @@ Value StringPrototype::starts_with(Interpreter& interpreter) | ||||||
|     auto* this_object = interpreter.this_value().to_object(interpreter.heap()); |     auto* this_object = interpreter.this_value().to_object(interpreter.heap()); | ||||||
|     if (!this_object) |     if (!this_object) | ||||||
|         return {}; |         return {}; | ||||||
|     if (interpreter.call_frame().arguments.is_empty()) |     if (!interpreter.argument_count()) | ||||||
|         return Value(false); |         return Value(false); | ||||||
|     auto search_string = interpreter.call_frame().arguments[0].to_string(); |     auto search_string = interpreter.argument(0).to_string(); | ||||||
|     auto search_string_length = static_cast<i32>(search_string.length()); |     auto search_string_length = static_cast<i32>(search_string.length()); | ||||||
|     i32 position = 0; |     i32 position = 0; | ||||||
|     if (interpreter.call_frame().arguments.size() > 1) { |     if (interpreter.argument_count() > 1) { | ||||||
|         auto number = interpreter.call_frame().arguments[1].to_number(); |         auto number = interpreter.argument(1).to_number(); | ||||||
|         if (!number.is_nan()) |         if (!number.is_nan()) | ||||||
|             position = number.to_i32(); |             position = number.to_i32(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -211,9 +211,9 @@ ReplObject::~ReplObject() | ||||||
| 
 | 
 | ||||||
| JS::Value ReplObject::exit_interpreter(JS::Interpreter& interpreter) | JS::Value ReplObject::exit_interpreter(JS::Interpreter& interpreter) | ||||||
| { | { | ||||||
|     if (interpreter.call_frame().arguments.is_empty()) |     if (!interpreter.argument_count()) | ||||||
|         exit(0); |         exit(0); | ||||||
|     int exit_code = interpreter.call_frame().arguments[0].to_number().as_double(); |     int exit_code = interpreter.argument(0).to_number().as_double(); | ||||||
|     exit(exit_code); |     exit(exit_code); | ||||||
|     return JS::js_undefined(); |     return JS::js_undefined(); | ||||||
| } | } | ||||||
|  | @ -230,10 +230,10 @@ JS::Value ReplObject::repl_help(JS::Interpreter& interpreter) | ||||||
| 
 | 
 | ||||||
| JS::Value ReplObject::load_file(JS::Interpreter& interpreter) | JS::Value ReplObject::load_file(JS::Interpreter& interpreter) | ||||||
| { | { | ||||||
|     if (interpreter.call_frame().arguments.is_empty()) |     if (!interpreter.argument_count()) | ||||||
|         return JS::Value(false); |         return JS::Value(false); | ||||||
|     Vector<JS::Value> files = interpreter.call_frame().arguments; | 
 | ||||||
|     for (JS::Value file : files) { |     for (auto& file : interpreter.call_frame().arguments) { | ||||||
|         String file_name = file.as_string()->string(); |         String file_name = file.as_string()->string(); | ||||||
|         auto js_file = Core::File::construct(file_name); |         auto js_file = Core::File::construct(file_name); | ||||||
|         if (!js_file->open(Core::IODevice::ReadOnly)) { |         if (!js_file->open(Core::IODevice::ReadOnly)) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling