1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:17:44 +00:00

LibJS: Add PrivateEnvironment

This commit is contained in:
davidot 2021-10-11 20:29:31 +02:00 committed by Linus Groh
parent eeb42c21d1
commit 13ead80ee6
13 changed files with 154 additions and 27 deletions

View file

@ -199,7 +199,9 @@ Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter&
MUST(scope->create_immutable_binding(global_object, name(), false));
}
auto closure = ECMAScriptFunctionObject::create(global_object, used_name, body(), parameters(), function_length(), scope, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function());
auto* private_scope = interpreter.vm().running_execution_context().private_environment;
auto closure = ECMAScriptFunctionObject::create(global_object, used_name, body(), parameters(), function_length(), scope, private_scope, kind(), is_strict_mode(), might_need_arguments_object(), contains_direct_call_to_eval(), is_arrow_function());
// FIXME: 6. Perform SetFunctionName(closure, name).
// FIXME: 7. Perform MakeConstructor(closure).
@ -1232,7 +1234,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
auto body = create_ast_node<ExpressionStatement>(m_initializer->source_range(), copy_initializer.release_nonnull());
// FIXME: A potential optimization is not creating the functions here since these are never directly accessible.
auto name = property_key.is_number() ? property_key.to_string() : property_key.to_string_or_symbol().to_display_string();
initializer = ECMAScriptFunctionObject::create(interpreter.global_object(), name, *body, {}, 0, interpreter.lexical_environment(), FunctionKind::Regular, false, false);
initializer = ECMAScriptFunctionObject::create(interpreter.global_object(), name, *body, {}, 0, interpreter.lexical_environment(), interpreter.vm().running_execution_context().private_environment, FunctionKind::Regular, false, false);
initializer->set_home_object(&target);
}
@ -1248,9 +1250,10 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_evaluation(Interpreter& interpreter, GlobalObject& global_object, Object& home_object) const
{
auto* lexical_environment = interpreter.vm().running_execution_context().lexical_environment;
auto* private_scope = interpreter.vm().running_execution_context().private_environment;
// Note: The function bodyFunction is never directly accessible to ECMAScript code.
auto* body_function = ECMAScriptFunctionObject::create(global_object, "", *m_function_body, {}, 0, lexical_environment, FunctionKind::Regular, true, false, m_contains_direct_call_to_eval, false);
auto* body_function = ECMAScriptFunctionObject::create(global_object, "", *m_function_body, {}, 0, lexical_environment, private_scope, FunctionKind::Regular, true, false, m_contains_direct_call_to_eval, false);
body_function->set_home_object(&home_object);
return ClassValue { normal_completion(body_function) };
@ -1303,7 +1306,8 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
if (!binding_name.is_null())
MUST(class_scope->create_immutable_binding(global_object, binding_name, true));
// FIXME: Add classPrivateEnvironment
auto* outer_private_environment = vm.running_execution_context().private_environment;
auto* class_private_environment = new_private_environment(vm, outer_private_environment);
// FIXME: Append names to private environment
@ -1355,7 +1359,10 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
VERIFY(prototype);
vm.running_execution_context().lexical_environment = class_scope;
// FIXME: Activate the class private environment
vm.running_execution_context().private_environment = class_private_environment;
ScopeGuard restore_private_environment = [&] {
vm.running_execution_context().private_environment = outer_private_environment;
};
// FIXME: Step 14.a is done in the parser. But maybe it shouldn't?
Value class_constructor_value = m_constructor->execute(interpreter, global_object);
@ -3284,6 +3291,7 @@ void ScopeNode::block_declaration_instantiation(GlobalObject& global_object, Env
{
// See also B.3.2.6 Changes to BlockDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-blockdeclarationinstantiation
VERIFY(environment);
auto* private_environment = global_object.vm().running_execution_context().private_environment;
for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
auto is_constant_declaration = declaration.is_constant_declaration();
declaration.for_each_bound_name([&](auto const& name) {
@ -3297,7 +3305,7 @@ void ScopeNode::block_declaration_instantiation(GlobalObject& global_object, Env
if (is<FunctionDeclaration>(declaration)) {
auto& function_declaration = static_cast<FunctionDeclaration const&>(declaration);
auto* function = ECMAScriptFunctionObject::create(global_object, function_declaration.name(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), environment, function_declaration.kind(), function_declaration.is_strict_mode(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval());
auto* function = ECMAScriptFunctionObject::create(global_object, function_declaration.name(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval());
VERIFY(is<DeclarativeEnvironment>(*environment));
static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, global_object, function_declaration.name(), function);
}
@ -3424,6 +3432,8 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
declared_function_names.clear();
}
PrivateEnvironment* private_environment = nullptr;
for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
declaration.for_each_bound_name([&](auto const& name) {
if (declaration.is_constant_declaration())
@ -3440,7 +3450,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
});
for (auto& declaration : functions_to_initialize) {
auto* function = ECMAScriptFunctionObject::create(global_object, declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), &global_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval());
auto* function = ECMAScriptFunctionObject::create(global_object, declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), &global_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval());
global_environment.create_global_function_binding(declaration.name(), function, false);
if (auto* exception = interpreter.exception())
return throw_completion(exception->value());

View file

@ -353,7 +353,7 @@ void Call::execute_impl(Bytecode::Interpreter& interpreter) const
void NewFunction::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& vm = interpreter.vm();
interpreter.accumulator() = ECMAScriptFunctionObject::create(interpreter.global_object(), m_function_node.name(), m_function_node.body(), m_function_node.parameters(), m_function_node.function_length(), vm.lexical_environment(), m_function_node.kind(), m_function_node.is_strict_mode(), m_function_node.might_need_arguments_object(), m_function_node.is_arrow_function());
interpreter.accumulator() = ECMAScriptFunctionObject::create(interpreter.global_object(), m_function_node.name(), m_function_node.body(), m_function_node.parameters(), m_function_node.function_length(), vm.lexical_environment(), vm.running_execution_context().private_environment, m_function_node.kind(), m_function_node.is_strict_mode(), m_function_node.might_need_arguments_object(), m_function_node.is_arrow_function());
}
void Return::execute_impl(Bytecode::Interpreter& interpreter) const

View file

@ -107,6 +107,7 @@ set(SOURCES
Runtime/ObjectEnvironment.cpp
Runtime/ObjectPrototype.cpp
Runtime/PrimitiveString.cpp
Runtime/PrivateEnvironment.cpp
Runtime/Promise.cpp
Runtime/PromiseConstructor.cpp
Runtime/PromiseJobs.cpp

View file

@ -418,6 +418,11 @@ FunctionEnvironment* new_function_environment(ECMAScriptFunctionObject& function
return env;
}
PrivateEnvironment* new_private_environment(VM& vm, PrivateEnvironment* outer)
{
return vm.heap().allocate<PrivateEnvironment>(vm.current_realm()->global_object(), outer);
}
// 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment
Environment& get_this_environment(VM& vm)
{
@ -490,12 +495,15 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
Environment* lexical_environment;
Environment* variable_environment;
PrivateEnvironment* private_environment;
if (direct == EvalMode::Direct) {
lexical_environment = new_declarative_environment(*running_context.lexical_environment);
variable_environment = running_context.variable_environment;
private_environment = running_context.private_environment;
} else {
lexical_environment = new_declarative_environment(eval_realm->global_environment());
variable_environment = &eval_realm->global_environment();
private_environment = nullptr;
}
if (strict_eval)
@ -515,13 +523,14 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
eval_context.realm = eval_realm;
eval_context.variable_environment = variable_environment;
eval_context.lexical_environment = lexical_environment;
eval_context.private_environment = private_environment;
vm.push_execution_context(eval_context, eval_realm->global_object());
ScopeGuard pop_guard = [&] {
vm.pop_execution_context();
};
TRY(eval_declaration_instantiation(vm, eval_realm->global_object(), program, variable_environment, lexical_environment, strict_eval));
TRY(eval_declaration_instantiation(vm, eval_realm->global_object(), program, variable_environment, lexical_environment, private_environment, strict_eval));
auto& interpreter = vm.interpreter();
TemporaryChange scope_change_strict(vm.running_execution_context().is_strict_mode, strict_eval);
@ -535,7 +544,7 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
}
// 19.2.1.3 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict ), https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& global_object, Program const& program, Environment* variable_environment, Environment* lexical_environment, bool strict)
ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& global_object, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict)
{
// FIXME: I'm not sure if the global object is correct here. And this is quite a crucial spot!
GlobalEnvironment* global_var_environment = variable_environment->is_global_environment() ? static_cast<GlobalEnvironment*>(variable_environment) : nullptr;
@ -572,6 +581,8 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
}
}
// FIXME: Add Private identifiers check here.
HashTable<FlyString> declared_function_names;
Vector<FunctionDeclaration const&> functions_to_initialize;
program.for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) {
@ -690,7 +701,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
return throw_completion(exception->value());
for (auto& declaration : functions_to_initialize) {
auto* function = ECMAScriptFunctionObject::create(global_object, declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), lexical_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object());
auto* function = ECMAScriptFunctionObject::create(global_object, declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), lexical_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object());
if (global_var_environment) {
global_var_environment->create_global_function_binding(declaration.name(), function, true);
if (auto* exception = vm.exception())

View file

@ -10,6 +10,7 @@
#include <LibJS/AST.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/PrivateEnvironment.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
@ -17,6 +18,7 @@ namespace JS {
DeclarativeEnvironment* new_declarative_environment(Environment&);
ObjectEnvironment* new_object_environment(Object&, bool is_with_environment, Environment*);
FunctionEnvironment* new_function_environment(ECMAScriptFunctionObject&, Object* new_target);
PrivateEnvironment* new_private_environment(VM& vm, PrivateEnvironment* outer);
Environment& get_this_environment(VM&);
Object* get_super_constructor(VM&);
ThrowCompletionOr<Reference> make_super_property_reference(GlobalObject&, Value actual_this, StringOrSymbol const& property_key, bool strict);
@ -45,7 +47,7 @@ enum class EvalMode {
};
ThrowCompletionOr<Value> perform_eval(Value, GlobalObject&, CallerMode, EvalMode);
ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& global_object, Program const& program, Environment* variable_environment, Environment* lexical_environment, bool strict);
ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& global_object, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict);
// 7.3.13 Call ( F, V [ , argumentsList ] ), https://tc39.es/ecma262/#sec-call
template<typename... Args>

View file

@ -24,7 +24,7 @@
namespace JS {
ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_object, FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_scope, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function)
ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_object, FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_scope, PrivateEnvironment* private_scope, FunctionKind kind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function)
{
Object* prototype = nullptr;
switch (kind) {
@ -35,12 +35,13 @@ ECMAScriptFunctionObject* ECMAScriptFunctionObject::create(GlobalObject& global_
prototype = global_object.generator_function_prototype();
break;
}
return global_object.heap().allocate<ECMAScriptFunctionObject>(global_object, move(name), ecmascript_code, move(parameters), m_function_length, parent_scope, *prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function);
return global_object.heap().allocate<ECMAScriptFunctionObject>(global_object, move(name), ecmascript_code, move(parameters), m_function_length, parent_scope, private_scope, *prototype, kind, is_strict, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function);
}
ECMAScriptFunctionObject::ECMAScriptFunctionObject(FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> formal_parameters, i32 function_length, Environment* parent_scope, Object& prototype, FunctionKind kind, bool strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function)
ECMAScriptFunctionObject::ECMAScriptFunctionObject(FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> formal_parameters, i32 function_length, Environment* parent_scope, PrivateEnvironment* private_scope, Object& prototype, FunctionKind kind, bool strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function)
: FunctionObject(prototype)
, m_environment(parent_scope)
, m_private_environment(private_scope)
, m_formal_parameters(move(formal_parameters))
, m_ecmascript_code(ecmascript_code)
, m_realm(global_object().associated_realm())
@ -540,9 +541,9 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
});
VERIFY(!vm.exception());
auto* private_environment = callee_context.private_environment;
for (auto& declaration : functions_to_initialize) {
auto* function = ECMAScriptFunctionObject::create(global_object(), declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), lex_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval());
auto* function = ECMAScriptFunctionObject::create(global_object(), declaration.name(), declaration.body(), declaration.parameters(), declaration.function_length(), lex_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), declaration.might_need_arguments_object(), declaration.contains_direct_call_to_eval());
MUST(var_environment->set_mutable_binding(global_object(), declaration.name(), function, false));
}
@ -595,7 +596,7 @@ void ECMAScriptFunctionObject::prepare_for_ordinary_call(ExecutionContext& calle
callee_context.variable_environment = local_environment;
// 10. Set the PrivateEnvironment of calleeContext to F.[[PrivateEnvironment]].
// FIXME: We currently don't support private environments.
callee_context.private_environment = m_private_environment;
// 11. If callerContext is not already suspended, suspend callerContext.
// FIXME: We don't have this concept yet.

View file

@ -28,9 +28,9 @@ public:
Global,
};
static ECMAScriptFunctionObject* create(GlobalObject&, FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_scope, FunctionKind, bool is_strict, bool might_need_arguments_object = true, bool contains_direct_call_to_eval = true, bool is_arrow_function = false);
static ECMAScriptFunctionObject* create(GlobalObject&, FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_scope, PrivateEnvironment* private_scope, FunctionKind, bool is_strict, bool might_need_arguments_object = true, bool contains_direct_call_to_eval = true, bool is_arrow_function = false);
ECMAScriptFunctionObject(FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_scope, Object& prototype, FunctionKind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function);
ECMAScriptFunctionObject(FlyString name, Statement const& ecmascript_code, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, Environment* parent_scope, PrivateEnvironment* private_scope, Object& prototype, FunctionKind, bool is_strict, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function);
virtual void initialize(GlobalObject&) override;
virtual ~ECMAScriptFunctionObject();
@ -88,6 +88,7 @@ private:
// Internal Slots of ECMAScript Function Objects, https://tc39.es/ecma262/#table-internal-slots-of-ecmascript-function-objects
Environment* m_environment { nullptr }; // [[Environment]]
PrivateEnvironment* m_private_environment { nullptr }; // [[PrivateEnvironment]]
Vector<FunctionNode::Parameter> const m_formal_parameters; // [[FormalParameters]]
NonnullRefPtr<Statement> m_ecmascript_code; // [[ECMAScriptCode]]
ConstructorKind m_constructor_kind { ConstructorKind::Base }; // [[ConstructorKind]]

View file

@ -10,6 +10,7 @@
#include <AK/FlyString.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/PrivateEnvironment.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
@ -25,6 +26,7 @@ struct ExecutionContext {
Realm* realm { nullptr }; // [[Realm]]
Environment* lexical_environment { nullptr }; // [[LexicalEnvironment]]
Environment* variable_environment { nullptr }; // [[VariableEnvironment]]
PrivateEnvironment* private_environment { nullptr }; // [[PrivateEnvironment]]
ASTNode const* current_node { nullptr };
FlyString function_name;

View file

@ -62,7 +62,7 @@ Value GeneratorFunctionConstructor::construct(FunctionObject& new_target)
block.dump(executable);
}
return ECMAScriptFunctionObject::create(global_object(), function->name(), function->body(), function->parameters(), function->function_length(), vm().lexical_environment(), FunctionKind::Generator, function->is_strict_mode(), function->might_need_arguments_object());
return ECMAScriptFunctionObject::create(global_object(), function->name(), function->body(), function->parameters(), function->function_length(), vm().lexical_environment(), nullptr, FunctionKind::Generator, function->is_strict_mode(), function->might_need_arguments_object());
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/PrivateEnvironment.h>
namespace JS {
PrivateEnvironment::PrivateEnvironment(PrivateEnvironment* parent)
: m_outer_environment(parent)
, m_unique_id(s_next_id++)
{
// FIXME: We might want to delay getting the next unique id until required.
VERIFY(s_next_id != 0);
}
// Note: we start at one such that 0 can be invalid / default initialized.
u64 PrivateEnvironment::s_next_id = 1u;
PrivateName PrivateEnvironment::resolve_private_identifier(FlyString const& identifier) const
{
auto name_or_end = find_private_name(identifier);
if (!name_or_end.is_end())
return *name_or_end;
// Note: This verify ensures that we must either have a private name with a matching description
// or have an outer environment. Combined this means that we assert that we always return a PrivateName.
VERIFY(m_outer_environment);
return m_outer_environment->resolve_private_identifier(identifier);
}
void PrivateEnvironment::add_private_name(Badge<ClassExpression>, FlyString description)
{
// FIXME: there is a exception for getter setter pairs.
VERIFY(find_private_name(description).is_end());
m_private_names.empend(m_unique_id, move(description));
}
bool PrivateName::operator==(PrivateName const& rhs) const
{
return unique_id == rhs.unique_id && description == rhs.description;
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/FlyString.h>
#include <LibJS/Heap/Cell.h>
namespace JS {
struct PrivateName {
PrivateName(u64 unique_id, FlyString description)
: unique_id(unique_id)
, description(move(description))
{
}
u64 unique_id { 0 };
FlyString description;
bool operator==(PrivateName const& rhs) const;
};
class PrivateEnvironment : public Cell {
public:
explicit PrivateEnvironment(PrivateEnvironment* parent);
PrivateName resolve_private_identifier(FlyString const& identifier) const;
void add_private_name(Badge<ClassExpression>, FlyString description);
private:
virtual char const* class_name() const override { return "PrivateEnvironment"; }
auto find_private_name(FlyString const& description) const
{
return m_private_names.find_if([&](PrivateName const& private_name) {
return private_name.description == description;
});
}
static u64 s_next_id;
PrivateEnvironment* m_outer_environment { nullptr }; // [[OuterEnv]]
Vector<PrivateName> m_private_names; // [[Names]]
u64 m_unique_id;
};
}

View file

@ -108,7 +108,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(GlobalObject& global_object,
vm.push_execution_context(eval_context, eval_realm.global_object());
// 19. Let result be EvalDeclarationInstantiation(body, varEnv, lexEnv, null, strictEval).
auto eval_result = eval_declaration_instantiation(vm, eval_realm.global_object(), program, variable_environment, lexical_environment, strict_eval);
auto eval_result = eval_declaration_instantiation(vm, eval_realm.global_object(), program, variable_environment, lexical_environment, nullptr, strict_eval);
Completion result;

View file

@ -134,7 +134,7 @@ void EventTarget::set_event_handler_attribute(FlyString const& name, HTML::Event
dbgln("Failed to parse script in event handler attribute '{}'", name);
return;
}
auto* function = JS::ECMAScriptFunctionObject::create(target->script_execution_context()->realm().global_object(), name, program->body(), program->parameters(), program->function_length(), nullptr, JS::FunctionKind::Regular, false, false);
auto* function = JS::ECMAScriptFunctionObject::create(target->script_execution_context()->realm().global_object(), name, program->body(), program->parameters(), program->function_length(), nullptr, nullptr, JS::FunctionKind::Regular, false, false);
VERIFY(function);
listener = adopt_ref(*new DOM::EventListener(JS::make_handle(static_cast<JS::FunctionObject*>(function)), true));
}