diff --git a/Applications/Spreadsheet/Spreadsheet.cpp b/Applications/Spreadsheet/Spreadsheet.cpp index e40cb983ca..e90bfc9610 100644 --- a/Applications/Spreadsheet/Spreadsheet.cpp +++ b/Applications/Spreadsheet/Spreadsheet.cpp @@ -35,6 +35,7 @@ #include #include #include +#include namespace Spreadsheet { @@ -348,9 +349,7 @@ RefPtr Sheet::from_json(const JsonObject& object) break; case Cell::Formula: { auto& interpreter = sheet->interpreter(); - JS::MarkedValueList args { interpreter.heap() }; - args.append(JS::js_string(interpreter, obj.get("value").as_string())); - auto value = interpreter.call(parse_function, json, move(args)); + auto value = interpreter.call(parse_function, json, JS::js_string(interpreter, obj.get("value").as_string())); cell = make(obj.get("source").to_string(), move(value), sheet->make_weak_ptr()); break; } @@ -387,9 +386,7 @@ JsonObject Sheet::to_json() const if (it.value->kind == Cell::Formula) { data.set("source", it.value->data); auto json = m_interpreter->global_object().get("JSON"); - JS::MarkedValueList args(m_interpreter->heap()); - args.append(it.value->evaluated_data); - auto stringified = m_interpreter->call(json.as_object().get("stringify").as_function(), json, move(args)); + auto stringified = m_interpreter->call(json.as_object().get("stringify").as_function(), json, it.value->evaluated_data); data.set("value", stringified.to_string_without_side_effects()); } else { data.set("value", it.value->data); diff --git a/Libraries/LibJS/Heap/Heap.cpp b/Libraries/LibJS/Heap/Heap.cpp index 75b8b75fae..f615a43a26 100644 --- a/Libraries/LibJS/Heap/Heap.cpp +++ b/Libraries/LibJS/Heap/Heap.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index f301040dfe..797e3c8541 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -245,7 +245,7 @@ void Interpreter::gather_roots(Badge, HashTable& roots) roots.set(symbol.value); } -Value Interpreter::call(Function& function, Value this_value, Optional arguments) +Value Interpreter::call_internal(Function& function, Value this_value, Optional arguments) { ASSERT(!exception()); diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index cd5a1f33b4..6039f7beca 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -83,6 +83,21 @@ public: return interpreter; } + template + [[nodiscard]] ALWAYS_INLINE Value call(Function& function, Value this_value, Args... args) + { + // Are there any values in this argpack? + // args = [] -> if constexpr (false) + // args = [x, y, z] -> if constexpr ((void)x, true || ...) + if constexpr ((((void)args, true) || ...)) { + MarkedValueList arglist { heap() }; + (..., arglist.append(move(args))); + return call(function, this_value, move(arglist)); + } + + return call(function, this_value); + } + ~Interpreter(); Value run(GlobalObject&, const Statement&, ArgumentVector = {}, ScopeType = ScopeType::Block); @@ -118,7 +133,6 @@ public: void enter_scope(const ScopeNode&, ArgumentVector, ScopeType, GlobalObject&); void exit_scope(const ScopeNode&); - [[nodiscard]] Value call(Function&, Value this_value, Optional arguments = {}); Value construct(Function&, Function& new_target, Optional arguments, GlobalObject&); CallFrame& push_call_frame() @@ -215,6 +229,8 @@ public: private: Interpreter(); + [[nodiscard]] Value call_internal(Function&, Value this_value, Optional); + Heap m_heap; Value m_last_value; @@ -241,4 +257,13 @@ private: #undef __JS_ENUMERATE }; +template<> +[[nodiscard]] ALWAYS_INLINE Value Interpreter::call(Function& function, Value this_value, MarkedValueList arguments) { return call_internal(function, this_value, move(arguments)); } + +template<> +[[nodiscard]] ALWAYS_INLINE Value Interpreter::call(Function& function, Value this_value, Optional arguments) { return call_internal(function, this_value, move(arguments)); } + +template<> +[[nodiscard]] ALWAYS_INLINE Value Interpreter::call(Function& function, Value this_value) { return call(function, this_value, Optional {}); } + } diff --git a/Libraries/LibJS/Runtime/Accessor.h b/Libraries/LibJS/Runtime/Accessor.h index 612472e27e..d2fa5103e0 100644 --- a/Libraries/LibJS/Runtime/Accessor.h +++ b/Libraries/LibJS/Runtime/Accessor.h @@ -29,7 +29,6 @@ #include #include -#include namespace JS { @@ -63,10 +62,8 @@ public: { if (!m_setter) return; - MarkedValueList arguments(interpreter().heap()); - arguments.append(setter_value); // FIXME: It might be nice if we had a way to communicate to our caller if an exception happened after this. - (void)interpreter().call(*m_setter, this_value, move(arguments)); + (void)interpreter().call(*m_setter, this_value, setter_value); } void visit_children(Cell::Visitor& visitor) override diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Libraries/LibJS/Runtime/ArrayPrototype.cpp index 38a17ebdca..5d6eeb1846 100644 --- a/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -136,12 +135,7 @@ static void for_each_item(Interpreter& interpreter, GlobalObject& global_object, value = js_undefined(); } - MarkedValueList arguments(interpreter.heap()); - arguments.append(value); - arguments.append(Value((i32)i)); - arguments.append(this_object); - - auto callback_result = interpreter.call(*callback_function, this_value, move(arguments)); + auto callback_result = interpreter.call(*callback_function, this_value, value, Value((i32)i), this_object); if (interpreter.exception()) return; @@ -494,13 +488,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce) if (value.is_empty()) continue; - MarkedValueList arguments(interpreter.heap()); - arguments.append(accumulator); - arguments.append(value); - arguments.append(Value((i32)i)); - arguments.append(this_object); - - accumulator = interpreter.call(*callback_function, this_value, move(arguments)); + accumulator = interpreter.call(*callback_function, this_value, accumulator, value, Value((i32)i), this_object); if (interpreter.exception()) return {}; } @@ -553,13 +541,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right) if (value.is_empty()) continue; - MarkedValueList arguments(interpreter.heap()); - arguments.append(accumulator); - arguments.append(value); - arguments.append(Value(i)); - arguments.append(this_object); - - accumulator = interpreter.call(*callback_function, this_value, move(arguments)); + accumulator = interpreter.call(*callback_function, this_value, accumulator, value, Value((i32)i), this_object); if (interpreter.exception()) return {}; } diff --git a/Libraries/LibJS/Runtime/IteratorOperations.cpp b/Libraries/LibJS/Runtime/IteratorOperations.cpp index 64af1a3845..38c935a455 100644 --- a/Libraries/LibJS/Runtime/IteratorOperations.cpp +++ b/Libraries/LibJS/Runtime/IteratorOperations.cpp @@ -72,13 +72,10 @@ Object* iterator_next(Object& iterator, Value value) } Value result; - if (value.is_empty()) { + if (value.is_empty()) result = interpreter.call(next_method.as_function(), &iterator); - } else { - MarkedValueList arguments(iterator.heap()); - arguments.append(value); - result = interpreter.call(next_method.as_function(), &iterator, move(arguments)); - } + else + result = interpreter.call(next_method.as_function(), &iterator, value); if (interpreter.exception()) return {}; diff --git a/Libraries/LibJS/Runtime/JSONObject.cpp b/Libraries/LibJS/Runtime/JSONObject.cpp index a1aadf1e42..aea0030a36 100644 --- a/Libraries/LibJS/Runtime/JSONObject.cpp +++ b/Libraries/LibJS/Runtime/JSONObject.cpp @@ -56,7 +56,8 @@ JSONObject::~JSONObject() { } -String JSONObject::stringify_impl(Interpreter& interpreter, GlobalObject& global_object, Value value, Value replacer, Value space) { +String JSONObject::stringify_impl(Interpreter& interpreter, GlobalObject& global_object, Value value, Value replacer, Value space) +{ StringifyState state; @@ -154,19 +155,14 @@ String JSONObject::serialize_json_property(Interpreter& interpreter, StringifySt if (interpreter.exception()) return {}; if (to_json.is_function()) { - MarkedValueList arguments(interpreter.heap()); - arguments.append(js_string(interpreter, key.to_string())); - value = interpreter.call(to_json.as_function(), value, move(arguments)); + value = interpreter.call(to_json.as_function(), value, js_string(interpreter, key.to_string())); if (interpreter.exception()) return {}; } } if (state.replacer_function) { - MarkedValueList arguments(interpreter.heap()); - arguments.append(js_string(interpreter, key.to_string())); - arguments.append(value); - value = interpreter.call(*state.replacer_function, holder, move(arguments)); + value = interpreter.call(*state.replacer_function, holder, js_string(interpreter, key.to_string()), value); if (interpreter.exception()) return {}; } @@ -494,10 +490,8 @@ Value JSONObject::internalize_json_property(Interpreter& interpreter, Object* ho } } } - MarkedValueList arguments(interpreter.heap()); - arguments.append(js_string(interpreter, name.to_string())); - arguments.append(value); - return interpreter.call(reviver, Value(holder), move(arguments)); + + return interpreter.call(reviver, Value(holder), js_string(interpreter, name.to_string()), value); } } diff --git a/Libraries/LibJS/Runtime/ProxyObject.cpp b/Libraries/LibJS/Runtime/ProxyObject.cpp index a609f2e356..e63931bcbd 100644 --- a/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -89,9 +89,8 @@ Object* ProxyObject::prototype() interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "getPrototypeOf"); return nullptr; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target)); if (interpreter().exception()) return nullptr; if (!trap_result.is_object() && !trap_result.is_null()) { @@ -139,10 +138,8 @@ bool ProxyObject::set_prototype(Object* object) interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "setPrototypeOf"); return false; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - arguments.append(Value(object)); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean(); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), Value(object)).to_boolean(); if (interpreter().exception() || !trap_result) return false; if (m_target.is_extensible()) @@ -172,9 +169,8 @@ bool ProxyObject::is_extensible() const interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "isExtensible"); return {}; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean(); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target)).to_boolean(); if (interpreter().exception()) return false; if (trap_result != m_target.is_extensible()) { @@ -200,9 +196,8 @@ bool ProxyObject::prevent_extensions() interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "preventExtensions"); return {}; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean(); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target)).to_boolean(); if (interpreter().exception()) return false; if (trap_result && m_target.is_extensible()) { @@ -228,10 +223,8 @@ Optional ProxyObject::get_own_property_descriptor(const Prop interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor"); return {}; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - arguments.append(js_string(interpreter(), name.to_string())); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string())); if (interpreter().exception()) return {}; if (!trap_result.is_object() && !trap_result.is_undefined()) { @@ -285,11 +278,8 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "defineProperty"); return false; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - arguments.append(property_name.to_value(interpreter())); - arguments.append(Value(const_cast(&descriptor))); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean(); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), property_name.to_value(interpreter()), Value(const_cast(&descriptor))).to_boolean(); if (interpreter().exception() || !trap_result) return false; auto target_desc = m_target.get_own_property_descriptor(property_name); @@ -339,10 +329,8 @@ bool ProxyObject::has_property(const PropertyName& name) const interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "has"); return false; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - arguments.append(js_string(interpreter(), name.to_string())); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean(); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string())).to_boolean(); if (interpreter().exception()) return false; if (!trap_result) { @@ -379,11 +367,8 @@ Value ProxyObject::get(const PropertyName& name, Value) const interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "get"); return {}; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - arguments.append(js_string(interpreter(), name.to_string())); - arguments.append(Value(const_cast(this))); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string()), Value(const_cast(this))); if (interpreter().exception()) return {}; auto target_desc = m_target.get_own_property_descriptor(name); @@ -417,12 +402,7 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value) interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "set"); return false; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - arguments.append(js_string(interpreter(), name.to_string())); - arguments.append(value); - arguments.append(Value(const_cast(this))); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean(); + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string()), value, Value(const_cast(this))).to_boolean(); if (interpreter().exception() || !trap_result) return false; auto target_desc = m_target.get_own_property_descriptor(name); @@ -455,10 +435,8 @@ Value ProxyObject::delete_property(const PropertyName& name) interpreter().throw_exception(ErrorType::ProxyInvalidTrap, "deleteProperty"); return {}; } - MarkedValueList arguments(interpreter().heap()); - arguments.append(Value(&m_target)); - arguments.append(js_string(interpreter(), name.to_string())); - auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean(); + + auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string())).to_boolean(); if (interpreter().exception()) return {}; if (!trap_result) diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index 43140cafb0..b048190845 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -708,9 +708,8 @@ Value instance_of(Interpreter& interpreter, Value lhs, Value rhs) interpreter.throw_exception(ErrorType::NotAFunction, has_instance_method.to_string_without_side_effects().characters()); return {}; } - MarkedValueList arguments(interpreter.heap()); - arguments.append(lhs); - return Value(interpreter.call(has_instance_method.as_function(), rhs, move(arguments)).to_boolean()); + + return Value(interpreter.call(has_instance_method.as_function(), rhs, lhs).to_boolean()); } if (!rhs.is_function()) { diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp index dabe8c9cb5..5ff11610df 100644 --- a/Libraries/LibWeb/DOM/Node.cpp +++ b/Libraries/LibWeb/DOM/Node.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -38,8 +37,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -132,10 +131,8 @@ void Node::dispatch_event(NonnullRefPtr event) dbg() << "calling event listener with this=" << this_value; #endif auto* event_wrapper = wrap(global_object, *event); - JS::MarkedValueList arguments(global_object.heap()); - arguments.append(event_wrapper); auto& interpreter = document().interpreter(); - (void)interpreter.call(function, this_value, move(arguments)); + (void)interpreter.call(function, this_value, event_wrapper); if (interpreter.exception()) interpreter.clear_exception(); } diff --git a/Libraries/LibWeb/DOM/Window.cpp b/Libraries/LibWeb/DOM/Window.cpp index 0c09fe5bd7..35a3fa3786 100644 --- a/Libraries/LibWeb/DOM/Window.cpp +++ b/Libraries/LibWeb/DOM/Window.cpp @@ -28,12 +28,11 @@ #include #include #include -#include #include #include #include -#include #include +#include namespace Web::DOM { @@ -122,10 +121,8 @@ i32 Window::request_animation_frame(JS::Function& callback) i32 link_id = GUI::DisplayLink::register_callback([handle = make_handle(&callback)](i32 link_id) { auto& function = const_cast(static_cast(*handle.cell())); auto& interpreter = function.interpreter(); - JS::MarkedValueList arguments(interpreter.heap()); - arguments.append(JS::Value(fake_timestamp)); fake_timestamp += 10; - (void)interpreter.call(function, {}, move(arguments)); + (void)interpreter.call(function, {}, JS::Value(fake_timestamp)); if (interpreter.exception()) interpreter.clear_exception(); GUI::DisplayLink::unregister_callback(link_id); diff --git a/Libraries/LibWeb/DOM/XMLHttpRequest.cpp b/Libraries/LibWeb/DOM/XMLHttpRequest.cpp index b75d272701..cb95b89566 100644 --- a/Libraries/LibWeb/DOM/XMLHttpRequest.cpp +++ b/Libraries/LibWeb/DOM/XMLHttpRequest.cpp @@ -96,10 +96,8 @@ void XMLHttpRequest::dispatch_event(NonnullRefPtr event) auto& function = const_cast(*listener.listener).function(); auto& global_object = function.global_object(); auto* this_value = wrap(global_object, *this); - JS::MarkedValueList arguments(global_object.heap()); - arguments.append(wrap(global_object, *event)); auto& interpreter = function.interpreter(); - (void)interpreter.call(function, this_value, move(arguments)); + (void)interpreter.call(function, this_value, wrap(global_object, *this)); if (interpreter.exception()) interpreter.clear_exception(); } diff --git a/Userland/test-js.cpp b/Userland/test-js.cpp index dcc6399691..a26603993a 100644 --- a/Userland/test-js.cpp +++ b/Userland/test-js.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -265,7 +264,8 @@ JSFileResult TestRunner::run_file_test(const String& test_path) printf("Unable to parse test-common.js\n"); printf("%s\n", result.error().error.to_string().characters()); printf("%s\n", result.error().hint.characters()); - cleanup_and_exit();; + cleanup_and_exit(); + ; } m_test_program = result.value(); } diff --git a/Userland/test-web.cpp b/Userland/test-web.cpp index 087a270a7f..8c35510350 100644 --- a/Userland/test-web.cpp +++ b/Userland/test-web.cpp @@ -41,10 +41,9 @@ #include #include #include -#include #include -#include #include +#include #include #include