mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 08:35:09 +00:00
LibJS: Implement constructor/non-constructor function calls
This adds Function::construct() for constructor function calls via `new` keyword. NativeFunction doesn't have constructor behaviour by default, ScriptFunction simply calls call() in construct()
This commit is contained in:
parent
a27884e4be
commit
849e2c77e4
11 changed files with 66 additions and 1 deletions
|
@ -31,6 +31,7 @@
|
|||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/NativeFunction.h>
|
||||
#include <LibJS/Runtime/PrimitiveString.h>
|
||||
#include <LibJS/Runtime/ScriptFunction.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
|
@ -87,6 +88,14 @@ Value CallExpression::execute(Interpreter& interpreter) const
|
|||
if (interpreter.exception())
|
||||
return {};
|
||||
|
||||
if (is_new_expression()) {
|
||||
if (!callee.is_object()
|
||||
|| !callee.as_object()->is_function()
|
||||
|| (callee.as_object()->is_native_function()
|
||||
&& !static_cast<NativeFunction*>(callee.as_object())->has_constructor()))
|
||||
return interpreter.throw_exception<Error>("TypeError", String::format("%s is not a constructor", callee.to_string().characters()));
|
||||
}
|
||||
|
||||
if (!callee.is_object() || !callee.as_object()->is_function())
|
||||
return interpreter.throw_exception<Error>("TypeError", String::format("%s is not a function", callee.to_string().characters()));
|
||||
|
||||
|
@ -103,17 +112,19 @@ Value CallExpression::execute(Interpreter& interpreter) const
|
|||
}
|
||||
|
||||
Object* new_object = nullptr;
|
||||
Value result;
|
||||
if (is_new_expression()) {
|
||||
new_object = interpreter.heap().allocate<Object>();
|
||||
auto prototype = function->get("prototype");
|
||||
if (prototype.has_value() && prototype.value().is_object())
|
||||
new_object->set_prototype(prototype.value().as_object());
|
||||
call_frame.this_value = new_object;
|
||||
result = function->construct(interpreter);
|
||||
} else {
|
||||
call_frame.this_value = this_value;
|
||||
result = function->call(interpreter);
|
||||
}
|
||||
|
||||
auto result = function->call(interpreter);
|
||||
interpreter.pop_call_frame();
|
||||
|
||||
if (is_new_expression()) {
|
||||
|
@ -955,4 +966,5 @@ void SwitchCase::dump(int indent) const
|
|||
statement.dump(indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue