Browse Source

Fix error for static class methods named `prototype` (#2552)

This Pull Request changes the following:

- Remove wrong early errors for static class methods with the computed property name `prototype`.
- Switch static class method definition opcodes from `__define_own_property__` to `define_property_or_throw` to correctly throw runtime errors on property redefinitions.
pull/2559/head
raskad 2 years ago
parent
commit
9355c77e0b
  1. 2
      boa_engine/src/vm/opcode/define/class/getter.rs
  2. 2
      boa_engine/src/vm/opcode/define/class/method.rs
  3. 2
      boa_engine/src/vm/opcode/define/class/setter.rs
  4. 48
      boa_parser/src/parser/statement/declaration/hoistable/class_decl/mod.rs

2
boa_engine/src/vm/opcode/define/class/getter.rs

@ -151,7 +151,7 @@ impl Operation for DefineClassStaticGetterByValue {
.as_ref() .as_ref()
.and_then(PropertyDescriptor::set) .and_then(PropertyDescriptor::set)
.cloned(); .cloned();
class.__define_own_property__( class.define_property_or_throw(
key, key,
PropertyDescriptor::builder() PropertyDescriptor::builder()
.maybe_get(Some(function)) .maybe_get(Some(function))

2
boa_engine/src/vm/opcode/define/class/method.rs

@ -136,7 +136,7 @@ impl Operation for DefineClassStaticMethodByValue {
function_mut.set_home_object(class.clone()); function_mut.set_home_object(class.clone());
function_mut.set_class_object(class.clone()); function_mut.set_class_object(class.clone());
} }
class.__define_own_property__( class.define_property_or_throw(
key, key,
PropertyDescriptor::builder() PropertyDescriptor::builder()
.value(function) .value(function)

2
boa_engine/src/vm/opcode/define/class/setter.rs

@ -151,7 +151,7 @@ impl Operation for DefineClassStaticSetterByValue {
.as_ref() .as_ref()
.and_then(PropertyDescriptor::get) .and_then(PropertyDescriptor::get)
.cloned(); .cloned();
class.__define_own_property__( class.define_property_or_throw(
key, key,
PropertyDescriptor::builder() PropertyDescriptor::builder()
.maybe_set(Some(function)) .maybe_set(Some(function))

48
boa_parser/src/parser/statement/declaration/hoistable/class_decl/mod.rs

@ -723,7 +723,7 @@ where
match class_element_name { match class_element_name {
ClassElementName::PropertyName(property_name) if r#static => { ClassElementName::PropertyName(property_name) if r#static => {
if property_name.prop_name() == Some(Sym::PROTOTYPE) { if property_name.literal() == Some(Sym::PROTOTYPE) {
return Err(Error::general( return Err(Error::general(
"class may not have static method definitions named 'prototype'", "class may not have static method definitions named 'prototype'",
name_position, name_position,
@ -780,7 +780,7 @@ where
cursor.set_strict_mode(strict); cursor.set_strict_mode(strict);
match class_element_name { match class_element_name {
ClassElementName::PropertyName(property_name) if r#static => { ClassElementName::PropertyName(property_name) if r#static => {
if property_name.prop_name() == Some(Sym::PROTOTYPE) { if property_name.literal() == Some(Sym::PROTOTYPE) {
return Err(Error::general( return Err(Error::general(
"class may not have static method definitions named 'prototype'", "class may not have static method definitions named 'prototype'",
name_position, name_position,
@ -825,11 +825,11 @@ where
match class_element_name { match class_element_name {
ClassElementName::PropertyName(property_name) if r#static => { ClassElementName::PropertyName(property_name) if r#static => {
if property_name.prop_name() == Some(Sym::PROTOTYPE) { if property_name.literal() == Some(Sym::PROTOTYPE) {
return Err(Error::general( return Err(Error::general(
"class may not have static method definitions named 'prototype'", "class may not have static method definitions named 'prototype'",
name_position, name_position,
)); ));
} }
function::ClassElement::StaticMethodDefinition( function::ClassElement::StaticMethodDefinition(
property_name, property_name,
@ -957,13 +957,11 @@ where
body, body,
)); ));
if r#static { if r#static {
if let Some(name) = name.prop_name() { if name.literal() == Some(Sym::PROTOTYPE) {
if name == Sym::PROTOTYPE { return Err(Error::general(
return Err(Error::general( "class may not have static method definitions named 'prototype'",
"class may not have static method definitions named 'prototype'", name_position,
name_position, ));
));
}
} }
function::ClassElement::StaticMethodDefinition(name, method) function::ClassElement::StaticMethodDefinition(name, method)
} else { } else {
@ -1081,13 +1079,11 @@ where
cursor.set_strict_mode(strict); cursor.set_strict_mode(strict);
let method = MethodDefinition::Set(Function::new(None, params, body)); let method = MethodDefinition::Set(Function::new(None, params, body));
if r#static { if r#static {
if let Some(name) = name.prop_name() { if name.literal() == Some(Sym::PROTOTYPE) {
if name == Sym::PROTOTYPE { return Err(Error::general(
return Err(Error::general( "class may not have static method definitions named 'prototype'",
"class may not have static method definitions named 'prototype'", name_position,
name_position, ));
));
}
} }
function::ClassElement::StaticMethodDefinition(name, method) function::ClassElement::StaticMethodDefinition(name, method)
} else { } else {
@ -1253,13 +1249,11 @@ where
} }
} }
TokenKind::Punctuator(Punctuator::OpenParen) => { TokenKind::Punctuator(Punctuator::OpenParen) => {
if let Some(name) = name.prop_name() { if r#static && name.literal() == Some(Sym::PROTOTYPE) {
if r#static && name == Sym::PROTOTYPE { return Err(Error::general(
return Err(Error::general( "class may not have static method definitions named 'prototype'",
"class may not have static method definitions named 'prototype'", name_position,
name_position, ));
));
}
} }
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);

Loading…
Cancel
Save