Serenity Operating System

LibJS: Add argument(i) and argument_count() to Interpreter

Add some convenience accessors for retrieving arguments from the
current call frame.

+49 -34
+15
Libraries/LibJS/Interpreter.h
··· 107 107 void pop_call_frame() { m_call_stack.take_last(); } 108 108 const CallFrame& call_frame() { return m_call_stack.last(); } 109 109 110 + size_t argument_count() const 111 + { 112 + if (m_call_stack.is_empty()) 113 + return 0; 114 + return m_call_stack.last().arguments.size(); 115 + } 116 + 117 + Value argument(size_t index) const 118 + { 119 + if (m_call_stack.is_empty()) 120 + return {}; 121 + auto& arguments = m_call_stack.last().arguments; 122 + return index < arguments.size() ? arguments[index] : js_undefined(); 123 + } 124 + 110 125 Value this_value() const 111 126 { 112 127 if (m_call_stack.is_empty())
+2 -2
Libraries/LibJS/Runtime/ArrayPrototype.cpp
··· 50 50 if (!this_object) 51 51 return {}; 52 52 ASSERT(this_object->is_array()); 53 - if (interpreter.call_frame().arguments.is_empty()) 53 + if (!interpreter.argument_count()) 54 54 return js_undefined(); 55 - static_cast<Array*>(this_object)->push(interpreter.call_frame().arguments[0]); 55 + static_cast<Array*>(this_object)->push(interpreter.argument(0)); 56 56 return Value(static_cast<const Array*>(this_object)->length()); 57 57 } 58 58
+3 -3
Libraries/LibJS/Runtime/ConsoleObject.cpp
··· 43 43 44 44 Value ConsoleObject::log(Interpreter& interpreter) 45 45 { 46 - for (size_t i = 0; i < interpreter.call_frame().arguments.size(); ++i) { 47 - printf("%s", interpreter.call_frame().arguments[i].to_string().characters()); 48 - if (i != interpreter.call_frame().arguments.size() - 1) 46 + for (size_t i = 0; i < interpreter.argument_count(); ++i) { 47 + printf("%s", interpreter.argument(i).to_string().characters()); 48 + if (i != interpreter.argument_count() - 1) 49 49 putchar(' '); 50 50 } 51 51 putchar('\n');
+2 -2
Libraries/LibJS/Runtime/GlobalObject.cpp
··· 39 39 40 40 Value GlobalObject::is_nan(Interpreter& interpreter) 41 41 { 42 - if (interpreter.call_frame().arguments.size() < 1) 42 + if (interpreter.argument_count() < 1) 43 43 return js_undefined(); 44 - return Value(interpreter.call_frame().arguments[0].to_number().is_nan()); 44 + return Value(interpreter.argument(0).to_number().is_nan()); 45 45 } 46 46 47 47 }
+2 -2
Libraries/LibJS/Runtime/MathObject.cpp
··· 53 53 54 54 Value MathObject::abs(Interpreter& interpreter) 55 55 { 56 - if (interpreter.call_frame().arguments.is_empty()) 56 + if (!interpreter.argument_count()) 57 57 return js_nan(); 58 58 59 - auto number = interpreter.call_frame().arguments[0].to_number(); 59 + auto number = interpreter.argument(0).to_number(); 60 60 if (number.is_nan()) 61 61 return js_nan(); 62 62 return Value(number.as_double() >= 0 ? number.as_double() : -number.as_double());
+8 -8
Libraries/LibJS/Runtime/ObjectConstructor.cpp
··· 57 57 58 58 Value ObjectConstructor::get_own_property_names(Interpreter& interpreter) 59 59 { 60 - if (interpreter.call_frame().arguments.size() < 1) 60 + if (!interpreter.argument_count()) 61 61 return {}; 62 - auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap()); 62 + auto* object = interpreter.argument(0).to_object(interpreter.heap()); 63 63 if (interpreter.exception()) 64 64 return {}; 65 65 auto* result = interpreter.heap().allocate<Array>(); ··· 75 75 76 76 Value ObjectConstructor::get_prototype_of(Interpreter& interpreter) 77 77 { 78 - if (interpreter.call_frame().arguments.size() < 1) 78 + if (!interpreter.argument_count()) 79 79 return {}; 80 - auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap()); 80 + auto* object = interpreter.argument(0).to_object(interpreter.heap()); 81 81 if (interpreter.exception()) 82 82 return {}; 83 83 return object->prototype(); ··· 85 85 86 86 Value ObjectConstructor::set_prototype_of(Interpreter& interpreter) 87 87 { 88 - if (interpreter.call_frame().arguments.size() < 2) 88 + if (interpreter.argument_count() < 2) 89 89 return {}; 90 - if (!interpreter.call_frame().arguments[1].is_object()) 90 + if (!interpreter.argument(0).is_object()) 91 91 return {}; 92 - auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap()); 92 + auto* object = interpreter.argument(0).to_object(interpreter.heap()); 93 93 if (interpreter.exception()) 94 94 return {}; 95 - object->set_prototype(&const_cast<Object&>(interpreter.call_frame().arguments[1].as_object())); 95 + object->set_prototype(&const_cast<Object&>(interpreter.argument(1).as_object())); 96 96 return {}; 97 97 } 98 98
+3 -3
Libraries/LibJS/Runtime/ObjectPrototype.cpp
··· 51 51 auto* this_object = interpreter.this_value().to_object(interpreter.heap()); 52 52 if (!this_object) 53 53 return {}; 54 - if (interpreter.call_frame().arguments.is_empty()) 55 - return js_undefined(); 56 - return Value(this_object->has_own_property(interpreter.call_frame().arguments[0].to_string())); 54 + if (!interpreter.argument_count()) 55 + return {}; 56 + return Value(this_object->has_own_property(interpreter.argument(0).to_string())); 57 57 } 58 58 59 59 Value ObjectPrototype::to_string(Interpreter& interpreter)
+9 -9
Libraries/LibJS/Runtime/StringPrototype.cpp
··· 54 54 if (!this_object) 55 55 return {}; 56 56 i32 index = 0; 57 - if (!interpreter.call_frame().arguments.is_empty()) 58 - index = interpreter.call_frame().arguments[0].to_i32(); 57 + if (interpreter.argument_count()) 58 + index = interpreter.argument(0).to_i32(); 59 59 ASSERT(this_object->is_string_object()); 60 60 auto underlying_string = static_cast<const StringObject*>(this_object)->primitive_string()->string(); 61 61 if (index < 0 || index >= static_cast<i32>(underlying_string.length())) ··· 69 69 if (!this_object) 70 70 return {}; 71 71 ASSERT(this_object->is_string_object()); 72 - if (interpreter.call_frame().arguments.is_empty()) 72 + if (!interpreter.argument_count()) 73 73 return js_string(interpreter.heap(), String::empty()); 74 74 i32 count = 0; 75 - count = interpreter.call_frame().arguments[0].to_i32(); 75 + count = interpreter.argument(0).to_i32(); 76 76 if (count < 0) { 77 77 // FIXME: throw RangeError 78 - return js_undefined(); 78 + return {}; 79 79 } 80 80 auto* string_object = static_cast<StringObject*>(this_object); 81 81 StringBuilder builder; ··· 89 89 auto* this_object = interpreter.this_value().to_object(interpreter.heap()); 90 90 if (!this_object) 91 91 return {}; 92 - if (interpreter.call_frame().arguments.is_empty()) 92 + if (!interpreter.argument_count()) 93 93 return Value(false); 94 - auto search_string = interpreter.call_frame().arguments[0].to_string(); 94 + auto search_string = interpreter.argument(0).to_string(); 95 95 auto search_string_length = static_cast<i32>(search_string.length()); 96 96 i32 position = 0; 97 - if (interpreter.call_frame().arguments.size() > 1) { 98 - auto number = interpreter.call_frame().arguments[1].to_number(); 97 + if (interpreter.argument_count() > 1) { 98 + auto number = interpreter.argument(1).to_number(); 99 99 if (!number.is_nan()) 100 100 position = number.to_i32(); 101 101 }
+5 -5
Userland/js.cpp
··· 211 211 212 212 JS::Value ReplObject::exit_interpreter(JS::Interpreter& interpreter) 213 213 { 214 - if (interpreter.call_frame().arguments.is_empty()) 214 + if (!interpreter.argument_count()) 215 215 exit(0); 216 - int exit_code = interpreter.call_frame().arguments[0].to_number().as_double(); 216 + int exit_code = interpreter.argument(0).to_number().as_double(); 217 217 exit(exit_code); 218 218 return JS::js_undefined(); 219 219 } ··· 230 230 231 231 JS::Value ReplObject::load_file(JS::Interpreter& interpreter) 232 232 { 233 - if (interpreter.call_frame().arguments.is_empty()) 233 + if (!interpreter.argument_count()) 234 234 return JS::Value(false); 235 - Vector<JS::Value> files = interpreter.call_frame().arguments; 236 - for (JS::Value file : files) { 235 + 236 + for (auto& file : interpreter.call_frame().arguments) { 237 237 String file_name = file.as_string()->string(); 238 238 auto js_file = Core::File::construct(file_name); 239 239 if (!js_file->open(Core::IODevice::ReadOnly)) {