mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:17:36 +00:00
LibJS: Implement the object literal __proto__ property key special case
This commit is contained in:
parent
9fa78b1a05
commit
7ebb421ee9
4 changed files with 22 additions and 0 deletions
|
@ -2994,6 +2994,17 @@ Completion ObjectExpression::execute(Interpreter& interpreter, GlobalObject& glo
|
||||||
|
|
||||||
auto value = TRY(property.value().execute(interpreter, global_object)).release_value();
|
auto value = TRY(property.value().execute(interpreter, global_object)).release_value();
|
||||||
|
|
||||||
|
// 8. If isProtoSetter is true, then
|
||||||
|
if (property.type() == ObjectProperty::Type::ProtoSetter) {
|
||||||
|
// a. If Type(propValue) is either Object or Null, then
|
||||||
|
if (value.is_object() || value.is_null()) {
|
||||||
|
// i. Perform ! object.[[SetPrototypeOf]](propValue).
|
||||||
|
MUST(object->internal_set_prototype_of(value.is_object() ? &value.as_object() : nullptr));
|
||||||
|
}
|
||||||
|
// b. Return unused.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (value.is_function() && property.is_method())
|
if (value.is_function() && property.is_method())
|
||||||
static_cast<ECMAScriptFunctionObject&>(value.as_function()).set_home_object(object);
|
static_cast<ECMAScriptFunctionObject&>(value.as_function()).set_home_object(object);
|
||||||
|
|
||||||
|
|
|
@ -1648,6 +1648,7 @@ public:
|
||||||
Getter,
|
Getter,
|
||||||
Setter,
|
Setter,
|
||||||
Spread,
|
Spread,
|
||||||
|
ProtoSetter,
|
||||||
};
|
};
|
||||||
|
|
||||||
ObjectProperty(SourceRange source_range, NonnullRefPtr<Expression> key, RefPtr<Expression> value, Type property_type, bool is_method)
|
ObjectProperty(SourceRange source_range, NonnullRefPtr<Expression> key, RefPtr<Expression> value, Type property_type, bool is_method)
|
||||||
|
|
|
@ -1700,6 +1700,8 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||||
property_key = parse_property_key();
|
property_key = parse_property_key();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. Else if propKey is the String value "__proto__" and if IsComputedPropertyKey of PropertyName is false, then
|
||||||
|
// a. Let isProtoSetter be true.
|
||||||
bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is<StringLiteral>(*property_key) && static_cast<StringLiteral const&>(*property_key).value() == "__proto__";
|
bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is<StringLiteral>(*property_key) && static_cast<StringLiteral const&>(*property_key).value() == "__proto__";
|
||||||
|
|
||||||
if (property_type == ObjectProperty::Type::Getter || property_type == ObjectProperty::Type::Setter) {
|
if (property_type == ObjectProperty::Type::Getter || property_type == ObjectProperty::Type::Setter) {
|
||||||
|
@ -1741,6 +1743,8 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||||
syntax_error("Property name '__proto__' must not appear more than once in object literal");
|
syntax_error("Property name '__proto__' must not appear more than once in object literal");
|
||||||
has_direct_proto_property = true;
|
has_direct_proto_property = true;
|
||||||
}
|
}
|
||||||
|
if (is_proto && property_type == ObjectProperty::Type::KeyValue)
|
||||||
|
property_type = ObjectProperty::Type::ProtoSetter;
|
||||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_key, parse_expression(2), property_type, false));
|
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_key, parse_expression(2), property_type, false));
|
||||||
} else if (property_key && property_value) {
|
} else if (property_key && property_value) {
|
||||||
if (m_state.strict_mode && is<StringLiteral>(*property_key)) {
|
if (m_state.strict_mode && is<StringLiteral>(*property_key)) {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
test("__proto__ property", () => {
|
||||||
|
expect(Object.getPrototypeOf({ __proto__: null })).toBeNull();
|
||||||
|
expect(Object.getPrototypeOf({ __proto__: Array.prototype })).toEqual(Array.prototype);
|
||||||
|
expect(Object.getPrototypeOf({ "__proto__": Array.prototype })).toEqual(Array.prototype); // prettier-ignore
|
||||||
|
expect(Object.getOwnPropertyNames({ __proto__: Array.prototype, test: 1 })).toEqual(["test"]);
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue