From 9eed7444de6d407dee6757485d9cc48f5f9384b0 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 28 Jun 2021 01:44:58 +0200 Subject: [PATCH] LibJS: Implement the CreateUnmappedArgumentsObject abstract operation --- .../LibJS/Runtime/AbstractOperations.cpp | 34 +++++++++++++++++++ .../LibJS/Runtime/AbstractOperations.h | 1 + Userland/Libraries/LibJS/Runtime/VM.cpp | 14 +++++--- Userland/Libraries/LibJS/Runtime/VM.h | 2 +- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 9bd057ec8d..149d10ae6b 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -204,4 +206,36 @@ Value perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller return interpreter.execute_statement(caller_realm, program).value_or(js_undefined()); } +// 10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList ), https://tc39.es/ecma262/#sec-createunmappedargumentsobject +Object* create_unmapped_arguments_object(GlobalObject& global_object, Vector const& arguments) +{ + auto& vm = global_object.vm(); + // FIXME: This should use OrdinaryObjectCreate + auto* object = Object::create(global_object, global_object.object_prototype()); + if (vm.exception()) + return nullptr; + + // 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }). + auto length = arguments.size(); + object->define_property(vm.names.length, Value(length), Attribute::Writable | Attribute::Configurable); + if (vm.exception()) + return nullptr; + + object->define_property(*vm.well_known_symbol_iterator(), global_object.array_prototype()->get(vm.names.values), Attribute::Writable | Attribute::Configurable); + + for (auto& argument : arguments) + object->indexed_properties().append(argument); + + // FIXME: 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }). + PropertyAttributes attributes; + attributes.set_has_configurable(); + attributes.set_has_enumerable(); + + object->define_property(vm.names.callee, js_undefined(), attributes); + if (vm.exception()) + return nullptr; + + return object; +} + } diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index 7cd70f8ead..d8279e28ca 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -23,6 +23,7 @@ MarkedValueList create_list_from_array_like(GlobalObject&, Value, Function const& arguments); enum class CallerMode { Strict, diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index e97845629e..e80d6da9ff 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -369,10 +369,16 @@ Value VM::get_variable(const FlyString& name, GlobalObject& global_object) if (possible_match.has_value()) return possible_match.value().value; if (!context.arguments_object) { - context.arguments_object = Array::create(global_object); - context.arguments_object->put(names.callee, context.function); - for (auto argument : context.arguments) { - context.arguments_object->indexed_properties().append(argument); + if (context.function->is_strict_mode()) { + context.arguments_object = create_unmapped_arguments_object(global_object, context.arguments); + } else { + // FIXME: This code path is completely ad-hoc. + context.arguments_object = Array::create(global_object); + context.arguments_object->put(names.callee, context.function); + + for (auto argument : context.arguments) { + context.arguments_object->indexed_properties().append(argument); + } } } return context.arguments_object; diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index 1f8698c67a..d70900407f 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -48,7 +48,7 @@ struct ExecutionContext { FunctionObject* function { nullptr }; Value this_value; Vector arguments; - Array* arguments_object { nullptr }; + Object* arguments_object { nullptr }; EnvironmentRecord* lexical_environment { nullptr }; EnvironmentRecord* variable_environment { nullptr }; bool is_strict_mode { false };