mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:17:44 +00:00
LibJS: Add PrivateEnvironment
This commit is contained in:
parent
eeb42c21d1
commit
13ead80ee6
13 changed files with 154 additions and 27 deletions
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
47
Userland/Libraries/LibJS/Runtime/PrivateEnvironment.cpp
Normal file
47
Userland/Libraries/LibJS/Runtime/PrivateEnvironment.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
52
Userland/Libraries/LibJS/Runtime/PrivateEnvironment.h
Normal file
52
Userland/Libraries/LibJS/Runtime/PrivateEnvironment.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue