mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-21 02:08:12 +03:00
LibJS: Replace Object's create_empty() with create() taking a prototype
This now matches the spec's OrdinaryObjectCreate() across the board: instead of implicitly setting the created object's prototype to %Object.prototype% and then in many cases setting it to a nullptr right away, it now has an 'Object* prototype' parameter with _no default value_. This makes the code easier to compare with the spec, very clear in terms of what prototype is being used as well as avoiding unnecessary shape transitions. Also fixes a couple of cases were we weren't setting the correct prototype. There's no reason to assume that the object would not be empty (as in having own properties), so let's follow our existing pattern of Type::create(...) and simply call it 'create'.
This commit is contained in:
parent
7489189645
commit
317b88a8c3
Notes:
sideshowbarker
2024-07-18 12:09:30 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/317b88a8c39 Pull-request: https://github.com/SerenityOS/serenity/pull/8099 Reviewed-by: https://github.com/awesomekling ✅
@ -263,7 +263,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name)
|
||||
if (!position.has_value())
|
||||
return JS::js_undefined();
|
||||
|
||||
auto object = JS::Object::create_empty(global_object);
|
||||
auto object = JS::Object::create(global_object, global_object.object_prototype());
|
||||
object->put("column", JS::js_string(vm, sheet_object->m_sheet.column(position.value().column)));
|
||||
object->put("row", JS::Value((unsigned)position.value().row));
|
||||
|
||||
@ -293,7 +293,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::current_cell_position)
|
||||
|
||||
auto position = current_cell->position();
|
||||
|
||||
auto object = JS::Object::create_empty(global_object);
|
||||
auto object = JS::Object::create(global_object, global_object.object_prototype());
|
||||
object->put("column", JS::js_string(vm, sheet_object->m_sheet.column(position.column)));
|
||||
object->put("row", JS::Value((unsigned)position.row));
|
||||
|
||||
@ -377,7 +377,7 @@ JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::column_arithmetic)
|
||||
}
|
||||
|
||||
WorkbookObject::WorkbookObject(Workbook& workbook)
|
||||
: JS::Object(*JS::Object::create_empty(workbook.global_object()))
|
||||
: JS::Object(*JS::Object::create(workbook.global_object(), workbook.global_object().object_prototype()))
|
||||
, m_workbook(workbook)
|
||||
{
|
||||
}
|
||||
|
@ -773,7 +773,6 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
|
||||
return {};
|
||||
}
|
||||
class_constructor->set_constructor_kind(Function::ConstructorKind::Derived);
|
||||
Object* prototype = Object::create_empty(global_object);
|
||||
|
||||
Object* super_constructor_prototype = nullptr;
|
||||
if (!super_constructor.is_null()) {
|
||||
@ -787,7 +786,7 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
|
||||
if (super_constructor_prototype_value.is_object())
|
||||
super_constructor_prototype = &super_constructor_prototype_value.as_object();
|
||||
}
|
||||
prototype->set_prototype(super_constructor_prototype);
|
||||
auto* prototype = Object::create(global_object, super_constructor_prototype);
|
||||
|
||||
prototype->define_property(vm.names.constructor, class_constructor, 0);
|
||||
if (interpreter.exception())
|
||||
@ -1683,7 +1682,7 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
|
||||
{
|
||||
InterpreterNodeScope node_scope { interpreter, *this };
|
||||
|
||||
auto* object = Object::create_empty(global_object);
|
||||
auto* object = Object::create(global_object, global_object.object_prototype());
|
||||
for (auto& property : m_properties) {
|
||||
auto key = property.key().execute(interpreter, global_object);
|
||||
if (interpreter.exception())
|
||||
|
@ -130,7 +130,7 @@ void NewString::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
|
||||
void NewObject::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
interpreter.accumulator() = Object::create_empty(interpreter.global_object());
|
||||
interpreter.accumulator() = Object::create(interpreter.global_object(), interpreter.global_object().object_prototype());
|
||||
}
|
||||
|
||||
void ConcatString::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
@ -307,7 +307,7 @@ void PushLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) co
|
||||
void Yield::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto yielded_value = interpreter.accumulator().value_or(js_undefined());
|
||||
auto object = JS::Object::create_empty(interpreter.global_object());
|
||||
auto object = JS::Object::create(interpreter.global_object(), nullptr);
|
||||
object->put("result", yielded_value);
|
||||
if (m_continuation_label.has_value())
|
||||
object->put("continuation", Value(static_cast<double>(reinterpret_cast<u64>(&m_continuation_label->block()))));
|
||||
|
@ -75,8 +75,7 @@ void ArrayPrototype::initialize(GlobalObject& global_object)
|
||||
define_property(vm.well_known_symbol_iterator(), get(vm.names.values), attr);
|
||||
|
||||
// 23.1.3.34 Array.prototype [ @@unscopables ], https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
|
||||
Object* unscopable_list = create_empty(global_object);
|
||||
unscopable_list->set_prototype(nullptr);
|
||||
auto* unscopable_list = Object::create(global_object, nullptr);
|
||||
unscopable_list->put(vm.names.copyWithin, Value(true));
|
||||
unscopable_list->put(vm.names.entries, Value(true));
|
||||
unscopable_list->put(vm.names.fill, Value(true));
|
||||
|
@ -86,7 +86,7 @@ Value GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<V
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
auto result = Object::create_empty(global_object);
|
||||
auto result = Object::create(global_object, global_object.object_prototype());
|
||||
result->put("value", previous_generated_value);
|
||||
|
||||
if (m_done) {
|
||||
|
@ -124,7 +124,7 @@ MarkedValueList iterable_to_list(GlobalObject& global_object, Value iterable, Va
|
||||
Value create_iterator_result_object(GlobalObject& global_object, Value value, bool done)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto* object = Object::create_empty(global_object);
|
||||
auto* object = Object::create(global_object, global_object.object_prototype());
|
||||
object->define_property(vm.names.value, value);
|
||||
object->define_property(vm.names.done, Value(done));
|
||||
return object;
|
||||
|
@ -106,7 +106,7 @@ String JSONObject::stringify_impl(GlobalObject& global_object, Value value, Valu
|
||||
state.gap = String::empty();
|
||||
}
|
||||
|
||||
auto* wrapper = Object::create_empty(global_object);
|
||||
auto* wrapper = Object::create(global_object, global_object.object_prototype());
|
||||
wrapper->define_property(String::empty(), value);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
@ -396,11 +396,12 @@ JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse)
|
||||
}
|
||||
Value result = parse_json_value(global_object, json.value());
|
||||
if (reviver.is_function()) {
|
||||
auto* holder_object = Object::create_empty(global_object);
|
||||
holder_object->define_property(String::empty(), result);
|
||||
auto* root = Object::create(global_object, global_object.object_prototype());
|
||||
auto root_name = String::empty();
|
||||
root->define_property(root_name, result);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
return internalize_json_property(global_object, holder_object, String::empty(), reviver.as_function());
|
||||
return internalize_json_property(global_object, root, root_name, reviver.as_function());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -426,7 +427,7 @@ Value JSONObject::parse_json_value(GlobalObject& global_object, const JsonValue&
|
||||
|
||||
Object* JSONObject::parse_json_object(GlobalObject& global_object, const JsonObject& json_object)
|
||||
{
|
||||
auto* object = Object::create_empty(global_object);
|
||||
auto* object = Object::create(global_object, global_object.object_prototype());
|
||||
json_object.for_each_member([&](auto& key, auto& value) {
|
||||
object->define_property(key, parse_json_value(global_object, value));
|
||||
});
|
||||
@ -443,6 +444,7 @@ Array* JSONObject::parse_json_array(GlobalObject& global_object, const JsonArray
|
||||
return array;
|
||||
}
|
||||
|
||||
// 25.5.1.1 InternalizeJSONProperty ( holder, name, reviver ), https://tc39.es/ecma262/#sec-internalizejsonproperty
|
||||
Value JSONObject::internalize_json_property(GlobalObject& global_object, Object* holder, const PropertyName& name, Function& reviver)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
@ -65,9 +65,15 @@ PropertyDescriptor PropertyDescriptor::from_dictionary(VM& vm, const Object& obj
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
Object* Object::create_empty(GlobalObject& global_object)
|
||||
// 10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinaryobjectcreate
|
||||
Object* Object::create(GlobalObject& global_object, Object* prototype)
|
||||
{
|
||||
return global_object.heap().allocate<Object>(global_object, *global_object.new_object_shape());
|
||||
if (!prototype)
|
||||
return global_object.heap().allocate<Object>(global_object, *global_object.empty_object_shape());
|
||||
else if (prototype == global_object.object_prototype())
|
||||
return global_object.heap().allocate<Object>(global_object, *global_object.new_object_shape());
|
||||
else
|
||||
return global_object.heap().allocate<Object>(global_object, *prototype);
|
||||
}
|
||||
|
||||
Object::Object(GlobalObjectTag)
|
||||
@ -425,12 +431,14 @@ Value Object::get_own_property_descriptor_object(const PropertyName& property_na
|
||||
VERIFY(property_name.is_valid());
|
||||
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto descriptor_opt = get_own_property_descriptor(property_name);
|
||||
if (!descriptor_opt.has_value())
|
||||
return js_undefined();
|
||||
auto descriptor = descriptor_opt.value();
|
||||
|
||||
auto* descriptor_object = Object::create_empty(global_object());
|
||||
auto* descriptor_object = Object::create(global_object, global_object.object_prototype());
|
||||
if (descriptor.is_data_descriptor()) {
|
||||
descriptor_object->define_property(vm.names.value, descriptor.value.value_or(js_undefined()));
|
||||
descriptor_object->define_property(vm.names.writable, Value(descriptor.attributes.is_writable()));
|
||||
|
@ -40,7 +40,7 @@ struct PropertyDescriptor {
|
||||
|
||||
class Object : public Cell {
|
||||
public:
|
||||
static Object* create_empty(GlobalObject&);
|
||||
static Object* create(GlobalObject&, Object* prototype);
|
||||
|
||||
explicit Object(Object& prototype);
|
||||
explicit Object(Shape&);
|
||||
|
@ -62,10 +62,13 @@ ObjectConstructor::~ObjectConstructor()
|
||||
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||
Value ObjectConstructor::call()
|
||||
{
|
||||
auto value = vm().argument(0);
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto value = vm.argument(0);
|
||||
if (value.is_nullish())
|
||||
return Object::create_empty(global_object());
|
||||
return value.to_object(global_object());
|
||||
return Object::create(global_object, global_object.object_prototype());
|
||||
return value.to_object(global_object);
|
||||
}
|
||||
|
||||
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||
@ -191,8 +194,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::from_entries)
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
auto* object = Object::create_empty(global_object);
|
||||
object->set_prototype(global_object.object_prototype());
|
||||
auto* object = Object::create(global_object, global_object.object_prototype());
|
||||
|
||||
get_iterator_values(global_object, iterable, [&](Value iterator_value) {
|
||||
if (vm.exception())
|
||||
@ -344,8 +346,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::create)
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* object = Object::create_empty(global_object);
|
||||
object->set_prototype(prototype);
|
||||
auto* object = Object::create(global_object, prototype);
|
||||
|
||||
if (!properties.is_undefined()) {
|
||||
object->define_properties(properties);
|
||||
|
@ -81,7 +81,7 @@ JS_DEFINE_NATIVE_FUNCTION(ProxyConstructor::revocable)
|
||||
});
|
||||
revoker->define_property(vm.names.length, Value(0));
|
||||
|
||||
auto* result = Object::create_empty(global_object);
|
||||
auto* result = Object::create(global_object, global_object.object_prototype());
|
||||
result->define_property(vm.names.proxy, proxy);
|
||||
result->define_property(vm.names.revoke, revoker);
|
||||
return result;
|
||||
|
@ -191,7 +191,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::exec)
|
||||
|
||||
Value groups = js_undefined();
|
||||
if (result.n_named_capture_groups > 0) {
|
||||
auto groups_object = create_empty(global_object);
|
||||
auto groups_object = Object::create(global_object, nullptr);
|
||||
for (auto& entry : result.named_capture_group_matches[0])
|
||||
groups_object->define_property(entry.key, js_string(vm, entry.value.view.to_string()));
|
||||
groups = move(groups_object);
|
||||
|
@ -286,8 +286,7 @@ void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, Global
|
||||
VERIFY(!property.pattern);
|
||||
JS::Value value_to_assign;
|
||||
if (property.is_rest) {
|
||||
auto* rest_object = Object::create_empty(global_object);
|
||||
rest_object->set_prototype(nullptr);
|
||||
auto* rest_object = Object::create(global_object, nullptr);
|
||||
for (auto& property : object->shape().property_table()) {
|
||||
if (!property.value.attributes.has_enumerable())
|
||||
continue;
|
||||
@ -406,7 +405,7 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
|
||||
|
||||
Object* new_object = nullptr;
|
||||
if (function.constructor_kind() == Function::ConstructorKind::Base) {
|
||||
new_object = Object::create_empty(global_object);
|
||||
new_object = Object::create(global_object, nullptr);
|
||||
if (environment)
|
||||
environment->bind_this_value(global_object, new_object);
|
||||
if (exception())
|
||||
|
@ -362,8 +362,7 @@ void WebAssemblyInstanceObject::initialize(JS::GlobalObject& global_object)
|
||||
Object::initialize(global_object);
|
||||
|
||||
VERIFY(!m_exports_object);
|
||||
m_exports_object = JS::Object::create_empty(global_object);
|
||||
m_exports_object->set_prototype(nullptr);
|
||||
m_exports_object = JS::Object::create(global_object, nullptr);
|
||||
auto& instance = this->instance();
|
||||
for (auto& export_ : instance.exports()) {
|
||||
export_.value().visit(
|
||||
|
Loading…
Reference in New Issue
Block a user