From bda39ef7ab3e05ce0d005721b0622aa52a2a6cbe Mon Sep 17 00:00:00 2001 From: Matthew Olsson Date: Thu, 25 Jun 2020 15:30:58 -0700 Subject: [PATCH] LibJS: Explicitly pass a "Function& new_target" to Function::construct This allows the proxy handler to pass the proper new.target to construct handlers. --- Libraries/LibJS/Interpreter.cpp | 2 +- Libraries/LibJS/Runtime/ArrayConstructor.cpp | 2 +- Libraries/LibJS/Runtime/ArrayConstructor.h | 2 +- Libraries/LibJS/Runtime/BigIntConstructor.cpp | 2 +- Libraries/LibJS/Runtime/BigIntConstructor.h | 2 +- Libraries/LibJS/Runtime/BooleanConstructor.cpp | 2 +- Libraries/LibJS/Runtime/BooleanConstructor.h | 2 +- Libraries/LibJS/Runtime/BoundFunction.cpp | 4 ++-- Libraries/LibJS/Runtime/BoundFunction.h | 2 +- Libraries/LibJS/Runtime/DateConstructor.cpp | 4 ++-- Libraries/LibJS/Runtime/DateConstructor.h | 2 +- Libraries/LibJS/Runtime/ErrorConstructor.cpp | 8 ++++---- Libraries/LibJS/Runtime/ErrorConstructor.h | 4 ++-- Libraries/LibJS/Runtime/ErrorTypes.h | 2 +- Libraries/LibJS/Runtime/Function.h | 2 +- Libraries/LibJS/Runtime/FunctionConstructor.cpp | 4 ++-- Libraries/LibJS/Runtime/FunctionConstructor.h | 2 +- Libraries/LibJS/Runtime/NativeFunction.cpp | 2 +- Libraries/LibJS/Runtime/NativeFunction.h | 2 +- Libraries/LibJS/Runtime/NumberConstructor.cpp | 2 +- Libraries/LibJS/Runtime/NumberConstructor.h | 2 +- Libraries/LibJS/Runtime/ObjectConstructor.cpp | 2 +- Libraries/LibJS/Runtime/ObjectConstructor.h | 2 +- Libraries/LibJS/Runtime/ProxyConstructor.cpp | 2 +- Libraries/LibJS/Runtime/ProxyConstructor.h | 2 +- Libraries/LibJS/Runtime/ProxyObject.cpp | 8 +++----- Libraries/LibJS/Runtime/ProxyObject.h | 2 +- Libraries/LibJS/Runtime/RegExpConstructor.cpp | 4 ++-- Libraries/LibJS/Runtime/RegExpConstructor.h | 2 +- Libraries/LibJS/Runtime/ScriptFunction.cpp | 2 +- Libraries/LibJS/Runtime/ScriptFunction.h | 2 +- Libraries/LibJS/Runtime/StringConstructor.cpp | 2 +- Libraries/LibJS/Runtime/StringConstructor.h | 2 +- Libraries/LibJS/Runtime/SymbolConstructor.cpp | 2 +- Libraries/LibJS/Runtime/SymbolConstructor.h | 2 +- Libraries/LibJS/Tests/Proxy.handler-construct.js | 15 +++++++++++++++ .../LibWeb/Bindings/XMLHttpRequestConstructor.cpp | 4 ++-- .../LibWeb/Bindings/XMLHttpRequestConstructor.h | 2 +- 38 files changed, 63 insertions(+), 50 deletions(-) diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index 3c585aef53..c39de4b998 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -268,7 +268,7 @@ Value Interpreter::construct(Function& function, Function& new_target, Optional< // If we are a Derived constructor, |this| has not been constructed before super is called. Value this_value = function.constructor_kind() == Function::ConstructorKind::Base ? new_object : Value {}; call_frame.this_value = this_value; - auto result = function.construct(*this); + auto result = function.construct(*this, new_target); this_value = current_environment()->get_this_binding(); pop_call_frame(); diff --git a/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Libraries/LibJS/Runtime/ArrayConstructor.cpp index 5758602e31..b66d6ea417 100644 --- a/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -79,7 +79,7 @@ Value ArrayConstructor::call(Interpreter& interpreter) return array; } -Value ArrayConstructor::construct(Interpreter& interpreter) +Value ArrayConstructor::construct(Interpreter& interpreter, Function&) { return call(interpreter); } diff --git a/Libraries/LibJS/Runtime/ArrayConstructor.h b/Libraries/LibJS/Runtime/ArrayConstructor.h index dd8df2db03..89c7697ecc 100644 --- a/Libraries/LibJS/Runtime/ArrayConstructor.h +++ b/Libraries/LibJS/Runtime/ArrayConstructor.h @@ -39,7 +39,7 @@ public: virtual ~ArrayConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/BigIntConstructor.cpp b/Libraries/LibJS/Runtime/BigIntConstructor.cpp index fb0ccf7dc0..ef9f35da55 100644 --- a/Libraries/LibJS/Runtime/BigIntConstructor.cpp +++ b/Libraries/LibJS/Runtime/BigIntConstructor.cpp @@ -72,7 +72,7 @@ Value BigIntConstructor::call(Interpreter& interpreter) return bigint; } -Value BigIntConstructor::construct(Interpreter& interpreter) +Value BigIntConstructor::construct(Interpreter& interpreter, Function&) { interpreter.throw_exception(ErrorType::NotAConstructor, "BigInt"); return {}; diff --git a/Libraries/LibJS/Runtime/BigIntConstructor.h b/Libraries/LibJS/Runtime/BigIntConstructor.h index 25a81625e5..3f6245be7d 100644 --- a/Libraries/LibJS/Runtime/BigIntConstructor.h +++ b/Libraries/LibJS/Runtime/BigIntConstructor.h @@ -39,7 +39,7 @@ public: virtual ~BigIntConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/BooleanConstructor.cpp b/Libraries/LibJS/Runtime/BooleanConstructor.cpp index b7b1bec89a..6bb425b794 100644 --- a/Libraries/LibJS/Runtime/BooleanConstructor.cpp +++ b/Libraries/LibJS/Runtime/BooleanConstructor.cpp @@ -54,7 +54,7 @@ Value BooleanConstructor::call(Interpreter& interpreter) return Value(interpreter.argument(0).to_boolean()); } -Value BooleanConstructor::construct(Interpreter& interpreter) +Value BooleanConstructor::construct(Interpreter& interpreter, Function&) { return BooleanObject::create(global_object(), interpreter.argument(0).to_boolean()); } diff --git a/Libraries/LibJS/Runtime/BooleanConstructor.h b/Libraries/LibJS/Runtime/BooleanConstructor.h index 1755123157..b7a6980bd6 100644 --- a/Libraries/LibJS/Runtime/BooleanConstructor.h +++ b/Libraries/LibJS/Runtime/BooleanConstructor.h @@ -39,7 +39,7 @@ public: virtual ~BooleanConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/BoundFunction.cpp b/Libraries/LibJS/Runtime/BoundFunction.cpp index 44f4985922..c6027a901b 100644 --- a/Libraries/LibJS/Runtime/BoundFunction.cpp +++ b/Libraries/LibJS/Runtime/BoundFunction.cpp @@ -54,14 +54,14 @@ Value BoundFunction::call(Interpreter& interpreter) return m_target_function->call(interpreter); } -Value BoundFunction::construct(Interpreter& interpreter) +Value BoundFunction::construct(Interpreter& interpreter, Function& new_target) { if (auto this_value = interpreter.this_value(global_object()); m_constructor_prototype && this_value.is_object()) { this_value.as_object().set_prototype(m_constructor_prototype); if (interpreter.exception()) return {}; } - return m_target_function->construct(interpreter); + return m_target_function->construct(interpreter, new_target); } LexicalEnvironment* BoundFunction::create_environment() diff --git a/Libraries/LibJS/Runtime/BoundFunction.h b/Libraries/LibJS/Runtime/BoundFunction.h index 1ee964e566..16197eb7a8 100644 --- a/Libraries/LibJS/Runtime/BoundFunction.h +++ b/Libraries/LibJS/Runtime/BoundFunction.h @@ -40,7 +40,7 @@ public: virtual Value call(Interpreter& interpreter) override; - virtual Value construct(Interpreter& interpreter) override; + virtual Value construct(Interpreter&, Function& new_target) override; virtual LexicalEnvironment* create_environment() override; diff --git a/Libraries/LibJS/Runtime/DateConstructor.cpp b/Libraries/LibJS/Runtime/DateConstructor.cpp index 068ac69c74..fa7f7f8038 100644 --- a/Libraries/LibJS/Runtime/DateConstructor.cpp +++ b/Libraries/LibJS/Runtime/DateConstructor.cpp @@ -54,13 +54,13 @@ DateConstructor::~DateConstructor() Value DateConstructor::call(Interpreter& interpreter) { - auto date = construct(interpreter); + auto date = construct(interpreter, *this); if (!date.is_object()) return {}; return js_string(interpreter, static_cast(date.as_object()).string()); } -Value DateConstructor::construct(Interpreter&) +Value DateConstructor::construct(Interpreter&, Function&) { // TODO: Support args struct timeval tv; diff --git a/Libraries/LibJS/Runtime/DateConstructor.h b/Libraries/LibJS/Runtime/DateConstructor.h index fcb2b022df..ed67b98ef0 100644 --- a/Libraries/LibJS/Runtime/DateConstructor.h +++ b/Libraries/LibJS/Runtime/DateConstructor.h @@ -39,7 +39,7 @@ public: virtual ~DateConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/ErrorConstructor.cpp b/Libraries/LibJS/Runtime/ErrorConstructor.cpp index b90fe8d391..994f28433b 100644 --- a/Libraries/LibJS/Runtime/ErrorConstructor.cpp +++ b/Libraries/LibJS/Runtime/ErrorConstructor.cpp @@ -49,10 +49,10 @@ ErrorConstructor::~ErrorConstructor() Value ErrorConstructor::call(Interpreter& interpreter) { - return construct(interpreter); + return construct(interpreter, *this); } -Value ErrorConstructor::construct(Interpreter& interpreter) +Value ErrorConstructor::construct(Interpreter& interpreter, Function&) { String message = ""; if (!interpreter.call_frame().arguments.is_empty() && !interpreter.call_frame().arguments[0].is_undefined()) { @@ -77,9 +77,9 @@ Value ErrorConstructor::construct(Interpreter& interpreter) ConstructorName::~ConstructorName() { } \ Value ConstructorName::call(Interpreter& interpreter) \ { \ - return construct(interpreter); \ + return construct(interpreter, *this); \ } \ - Value ConstructorName::construct(Interpreter& interpreter) \ + Value ConstructorName::construct(Interpreter& interpreter, Function&) \ { \ String message = ""; \ if (!interpreter.call_frame().arguments.is_empty() && !interpreter.call_frame().arguments[0].is_undefined()) { \ diff --git a/Libraries/LibJS/Runtime/ErrorConstructor.h b/Libraries/LibJS/Runtime/ErrorConstructor.h index 2208020a61..9b2a124b17 100644 --- a/Libraries/LibJS/Runtime/ErrorConstructor.h +++ b/Libraries/LibJS/Runtime/ErrorConstructor.h @@ -40,7 +40,7 @@ public: virtual ~ErrorConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } @@ -55,7 +55,7 @@ private: virtual void initialize(Interpreter&, GlobalObject&) override; \ virtual ~ConstructorName() override; \ virtual Value call(Interpreter&) override; \ - virtual Value construct(Interpreter&) override; \ + virtual Value construct(Interpreter&, Function& new_target) override; \ \ private: \ virtual bool has_constructor() const override { return true; } \ diff --git a/Libraries/LibJS/Runtime/ErrorTypes.h b/Libraries/LibJS/Runtime/ErrorTypes.h index fa872355e9..0c356f53f9 100644 --- a/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Libraries/LibJS/Runtime/ErrorTypes.h @@ -68,7 +68,7 @@ "Object prototype must not be %s on a super property access") \ M(ObjectPrototypeWrongType, "Prototype must be an object or null") \ M(ProxyCallWithNew, "Proxy must be called with the 'new' operator") \ - M(ProxyConstructBadReturnType, "Proxy handler's construct trap violates invariant: must return" \ + M(ProxyConstructBadReturnType, "Proxy handler's construct trap violates invariant: must return " \ "an object") \ M(ProxyConstructorBadType, "Expected %s argument of Proxy constructor to be object, got %s") \ M(ProxyDefinePropExistingConfigurable, "Proxy handler's defineProperty trap violates " \ diff --git a/Libraries/LibJS/Runtime/Function.h b/Libraries/LibJS/Runtime/Function.h index ada3bc81a1..613d27957c 100644 --- a/Libraries/LibJS/Runtime/Function.h +++ b/Libraries/LibJS/Runtime/Function.h @@ -44,7 +44,7 @@ public: virtual void initialize(Interpreter&, GlobalObject&) override { } virtual Value call(Interpreter&) = 0; - virtual Value construct(Interpreter&) = 0; + virtual Value construct(Interpreter&, Function& new_target) = 0; virtual const FlyString& name() const = 0; virtual LexicalEnvironment* create_environment() = 0; diff --git a/Libraries/LibJS/Runtime/FunctionConstructor.cpp b/Libraries/LibJS/Runtime/FunctionConstructor.cpp index 4e2ebf0134..75e7249741 100644 --- a/Libraries/LibJS/Runtime/FunctionConstructor.cpp +++ b/Libraries/LibJS/Runtime/FunctionConstructor.cpp @@ -53,10 +53,10 @@ FunctionConstructor::~FunctionConstructor() Value FunctionConstructor::call(Interpreter& interpreter) { - return construct(interpreter); + return construct(interpreter, *this); } -Value FunctionConstructor::construct(Interpreter& interpreter) +Value FunctionConstructor::construct(Interpreter& interpreter, Function&) { String parameters_source = ""; String body_source = ""; diff --git a/Libraries/LibJS/Runtime/FunctionConstructor.h b/Libraries/LibJS/Runtime/FunctionConstructor.h index 97b0aa9001..ba6eb8962d 100644 --- a/Libraries/LibJS/Runtime/FunctionConstructor.h +++ b/Libraries/LibJS/Runtime/FunctionConstructor.h @@ -39,7 +39,7 @@ public: virtual ~FunctionConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/NativeFunction.cpp b/Libraries/LibJS/Runtime/NativeFunction.cpp index 6d350ee9af..6bb5d8af8f 100644 --- a/Libraries/LibJS/Runtime/NativeFunction.cpp +++ b/Libraries/LibJS/Runtime/NativeFunction.cpp @@ -63,7 +63,7 @@ Value NativeFunction::call(Interpreter& interpreter) return m_native_function(interpreter, global_object()); } -Value NativeFunction::construct(Interpreter&) +Value NativeFunction::construct(Interpreter&, Function&) { return {}; } diff --git a/Libraries/LibJS/Runtime/NativeFunction.h b/Libraries/LibJS/Runtime/NativeFunction.h index 19cb64bd4e..61fd88cc19 100644 --- a/Libraries/LibJS/Runtime/NativeFunction.h +++ b/Libraries/LibJS/Runtime/NativeFunction.h @@ -42,7 +42,7 @@ public: virtual ~NativeFunction() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; virtual const FlyString& name() const override { return m_name; }; virtual bool has_constructor() const { return false; } diff --git a/Libraries/LibJS/Runtime/NumberConstructor.cpp b/Libraries/LibJS/Runtime/NumberConstructor.cpp index 5e3c378104..aa64d31ee9 100644 --- a/Libraries/LibJS/Runtime/NumberConstructor.cpp +++ b/Libraries/LibJS/Runtime/NumberConstructor.cpp @@ -72,7 +72,7 @@ Value NumberConstructor::call(Interpreter& interpreter) return interpreter.argument(0).to_number(interpreter); } -Value NumberConstructor::construct(Interpreter& interpreter) +Value NumberConstructor::construct(Interpreter& interpreter, Function&) { double number = 0; if (interpreter.argument_count()) { diff --git a/Libraries/LibJS/Runtime/NumberConstructor.h b/Libraries/LibJS/Runtime/NumberConstructor.h index ebde71db0b..c7ba5fefc8 100644 --- a/Libraries/LibJS/Runtime/NumberConstructor.h +++ b/Libraries/LibJS/Runtime/NumberConstructor.h @@ -39,7 +39,7 @@ public: virtual ~NumberConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Libraries/LibJS/Runtime/ObjectConstructor.cpp index 55efe1fb3f..7a0b4d246a 100644 --- a/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -69,7 +69,7 @@ Value ObjectConstructor::call(Interpreter& interpreter) return Object::create_empty(interpreter, global_object()); } -Value ObjectConstructor::construct(Interpreter& interpreter) +Value ObjectConstructor::construct(Interpreter& interpreter, Function&) { return call(interpreter); } diff --git a/Libraries/LibJS/Runtime/ObjectConstructor.h b/Libraries/LibJS/Runtime/ObjectConstructor.h index 782946eb3f..ddfec2c889 100644 --- a/Libraries/LibJS/Runtime/ObjectConstructor.h +++ b/Libraries/LibJS/Runtime/ObjectConstructor.h @@ -39,7 +39,7 @@ public: virtual ~ObjectConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/ProxyConstructor.cpp b/Libraries/LibJS/Runtime/ProxyConstructor.cpp index 89605876fd..152ea2ee88 100644 --- a/Libraries/LibJS/Runtime/ProxyConstructor.cpp +++ b/Libraries/LibJS/Runtime/ProxyConstructor.cpp @@ -54,7 +54,7 @@ Value ProxyConstructor::call(Interpreter& interpreter) return interpreter.throw_exception(ErrorType::ProxyCallWithNew); } -Value ProxyConstructor::construct(Interpreter& interpreter) +Value ProxyConstructor::construct(Interpreter& interpreter, Function&) { if (interpreter.argument_count() < 2) return interpreter.throw_exception(ErrorType::ProxyTwoArguments); diff --git a/Libraries/LibJS/Runtime/ProxyConstructor.h b/Libraries/LibJS/Runtime/ProxyConstructor.h index e914f2e3cc..adfe82215a 100644 --- a/Libraries/LibJS/Runtime/ProxyConstructor.h +++ b/Libraries/LibJS/Runtime/ProxyConstructor.h @@ -39,7 +39,7 @@ public: virtual ~ProxyConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/ProxyObject.cpp b/Libraries/LibJS/Runtime/ProxyObject.cpp index 43959d07d5..1d4b93fc26 100644 --- a/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -501,7 +501,7 @@ Value ProxyObject::call(Interpreter& interpreter) { return interpreter.call(trap.as_function(), Value(&m_handler), move(arguments)); } -Value ProxyObject::construct(Interpreter& interpreter) { +Value ProxyObject::construct(Interpreter& interpreter, Function& new_target) { if (!is_function()) return interpreter.throw_exception(ErrorType::NotAConstructor, Value(this).to_string_without_side_effects().characters()); @@ -513,7 +513,7 @@ Value ProxyObject::construct(Interpreter& interpreter) { if (interpreter.exception()) return {}; if (trap.is_empty() || trap.is_undefined() || trap.is_null()) - return static_cast(m_target).construct(interpreter); + return static_cast(m_target).construct(interpreter, new_target); if (!trap.is_function()) return interpreter.throw_exception(ErrorType::ProxyInvalidTrap, "construct"); @@ -524,9 +524,7 @@ Value ProxyObject::construct(Interpreter& interpreter) { arguments_array->indexed_properties().append(argument); }); arguments.values().append(arguments_array); - // FIXME: We need access to the actual newTarget property here. This is just - // a quick fix - arguments.values().append(Value(this)); + arguments.values().append(Value(&new_target)); auto result = interpreter.call(trap.as_function(), Value(&m_handler), move(arguments)); if (!result.is_object()) return interpreter.throw_exception(ErrorType::ProxyConstructBadReturnType); diff --git a/Libraries/LibJS/Runtime/ProxyObject.h b/Libraries/LibJS/Runtime/ProxyObject.h index f0f1a9e3ab..9c8b271161 100644 --- a/Libraries/LibJS/Runtime/ProxyObject.h +++ b/Libraries/LibJS/Runtime/ProxyObject.h @@ -40,7 +40,7 @@ public: virtual ~ProxyObject() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; virtual const FlyString& name() const override; virtual LexicalEnvironment* create_environment() override; diff --git a/Libraries/LibJS/Runtime/RegExpConstructor.cpp b/Libraries/LibJS/Runtime/RegExpConstructor.cpp index 4996f24a42..c461fda01a 100644 --- a/Libraries/LibJS/Runtime/RegExpConstructor.cpp +++ b/Libraries/LibJS/Runtime/RegExpConstructor.cpp @@ -50,10 +50,10 @@ RegExpConstructor::~RegExpConstructor() Value RegExpConstructor::call(Interpreter& interpreter) { - return construct(interpreter); + return construct(interpreter, *this); } -Value RegExpConstructor::construct(Interpreter& interpreter) +Value RegExpConstructor::construct(Interpreter& interpreter, Function&) { if (!interpreter.argument_count()) return RegExpObject::create(global_object(), "(?:)", ""); diff --git a/Libraries/LibJS/Runtime/RegExpConstructor.h b/Libraries/LibJS/Runtime/RegExpConstructor.h index 4c09b13b60..ece1ff54d6 100644 --- a/Libraries/LibJS/Runtime/RegExpConstructor.h +++ b/Libraries/LibJS/Runtime/RegExpConstructor.h @@ -39,7 +39,7 @@ public: virtual ~RegExpConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/ScriptFunction.cpp b/Libraries/LibJS/Runtime/ScriptFunction.cpp index 7c3b461649..d18718dd53 100644 --- a/Libraries/LibJS/Runtime/ScriptFunction.cpp +++ b/Libraries/LibJS/Runtime/ScriptFunction.cpp @@ -133,7 +133,7 @@ Value ScriptFunction::call(Interpreter& interpreter) return interpreter.run(global_object(), m_body, arguments, ScopeType::Function); } -Value ScriptFunction::construct(Interpreter& interpreter) +Value ScriptFunction::construct(Interpreter& interpreter, Function&) { if (m_is_arrow_function) return interpreter.throw_exception(ErrorType::NotAConstructor, m_name.characters()); diff --git a/Libraries/LibJS/Runtime/ScriptFunction.h b/Libraries/LibJS/Runtime/ScriptFunction.h index 304c229b04..3bf6e71759 100644 --- a/Libraries/LibJS/Runtime/ScriptFunction.h +++ b/Libraries/LibJS/Runtime/ScriptFunction.h @@ -45,7 +45,7 @@ public: const Vector& parameters() const { return m_parameters; }; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; virtual const FlyString& name() const override { return m_name; }; void set_name(const FlyString& name) { m_name = name; }; diff --git a/Libraries/LibJS/Runtime/StringConstructor.cpp b/Libraries/LibJS/Runtime/StringConstructor.cpp index c5901ea8fd..e6823b5315 100644 --- a/Libraries/LibJS/Runtime/StringConstructor.cpp +++ b/Libraries/LibJS/Runtime/StringConstructor.cpp @@ -65,7 +65,7 @@ Value StringConstructor::call(Interpreter& interpreter) return string; } -Value StringConstructor::construct(Interpreter& interpreter) +Value StringConstructor::construct(Interpreter& interpreter, Function&) { PrimitiveString* primitive_string = nullptr; if (!interpreter.argument_count()) diff --git a/Libraries/LibJS/Runtime/StringConstructor.h b/Libraries/LibJS/Runtime/StringConstructor.h index 3e7608920b..8aa78f8adf 100644 --- a/Libraries/LibJS/Runtime/StringConstructor.h +++ b/Libraries/LibJS/Runtime/StringConstructor.h @@ -39,7 +39,7 @@ public: virtual ~StringConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Runtime/SymbolConstructor.cpp b/Libraries/LibJS/Runtime/SymbolConstructor.cpp index 9080b2d56b..0e051128e2 100644 --- a/Libraries/LibJS/Runtime/SymbolConstructor.cpp +++ b/Libraries/LibJS/Runtime/SymbolConstructor.cpp @@ -74,7 +74,7 @@ Value SymbolConstructor::call(Interpreter& interpreter) return js_symbol(interpreter, interpreter.argument(0).to_string(interpreter), false); } -Value SymbolConstructor::construct(Interpreter& interpreter) +Value SymbolConstructor::construct(Interpreter& interpreter, Function&) { interpreter.throw_exception(ErrorType::NotAConstructor, "Symbol"); return {}; diff --git a/Libraries/LibJS/Runtime/SymbolConstructor.h b/Libraries/LibJS/Runtime/SymbolConstructor.h index 6e495cae4d..26c23c599c 100644 --- a/Libraries/LibJS/Runtime/SymbolConstructor.h +++ b/Libraries/LibJS/Runtime/SymbolConstructor.h @@ -39,7 +39,7 @@ public: virtual ~SymbolConstructor() override; virtual Value call(Interpreter&) override; - virtual Value construct(Interpreter&) override; + virtual Value construct(Interpreter&, Function& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Libraries/LibJS/Tests/Proxy.handler-construct.js b/Libraries/LibJS/Tests/Proxy.handler-construct.js index 60e15a3d70..c5f7bbf5b5 100644 --- a/Libraries/LibJS/Tests/Proxy.handler-construct.js +++ b/Libraries/LibJS/Tests/Proxy.handler-construct.js @@ -27,6 +27,21 @@ try { assert(new p(15).x === 15); assert(new p(15, true).x === 30); + let p; + function theNewTarget() {}; + const handler = { + construct(target, arguments, newTarget) { + assert(target === f); + assert(newTarget === theNewTarget); + if (arguments[1]) + return Reflect.construct(target, [arguments[0] * 2], newTarget); + return Reflect.construct(target, arguments, newTarget); + }, + }; + p = new Proxy(f, handler); + + Reflect.construct(p, [15], theNewTarget); + // Invariants [{}, [], new Proxy({}, {})].forEach(item => { assertThrowsError(() => { diff --git a/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp b/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp index c2682383ec..e1bb113a74 100644 --- a/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp +++ b/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp @@ -59,10 +59,10 @@ XMLHttpRequestConstructor::~XMLHttpRequestConstructor() JS::Value XMLHttpRequestConstructor::call(JS::Interpreter& interpreter) { - return construct(interpreter); + return construct(interpreter, *this); } -JS::Value XMLHttpRequestConstructor::construct(JS::Interpreter& interpreter) +JS::Value XMLHttpRequestConstructor::construct(JS::Interpreter& interpreter, Function&) { auto& window = static_cast(global_object()); return interpreter.heap().allocate(window, window, XMLHttpRequest::create(window.impl())); diff --git a/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.h b/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.h index ca5a8f8652..5c9b733e73 100644 --- a/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.h +++ b/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.h @@ -38,7 +38,7 @@ public: virtual ~XMLHttpRequestConstructor() override; virtual JS::Value call(JS::Interpreter&) override; - virtual JS::Value construct(JS::Interpreter&) override; + virtual JS::Value construct(JS::Interpreter& interpreter, Function& new_target) override; private: virtual bool has_constructor() const override { return true; }