Browse Source

Add default value for descructing property access arrays (#3738)

pull/3741/head
raskad 10 months ago committed by GitHub
parent
commit
2bed1fca2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      core/ast/src/expression/literal/array.rs
  2. 39
      core/ast/src/pattern.rs
  3. 11
      core/engine/src/bytecompiler/declaration/declaration_pattern.rs

2
core/ast/src/expression/literal/array.rs

@ -109,6 +109,7 @@ impl ArrayLiteral {
AssignTarget::Access(access) => { AssignTarget::Access(access) => {
bindings.push(ArrayPatternElement::PropertyAccess { bindings.push(ArrayPatternElement::PropertyAccess {
access: access.clone(), access: access.clone(),
default_init: Some(assign.rhs().clone()),
}); });
} }
AssignTarget::Pattern(pattern) => match pattern { AssignTarget::Pattern(pattern) => match pattern {
@ -143,6 +144,7 @@ impl ArrayLiteral {
Expression::PropertyAccess(access) => { Expression::PropertyAccess(access) => {
bindings.push(ArrayPatternElement::PropertyAccess { bindings.push(ArrayPatternElement::PropertyAccess {
access: access.clone(), access: access.clone(),
default_init: None,
}); });
} }
_ => return None, _ => return None,

39
core/ast/src/pattern.rs

@ -612,6 +612,8 @@ pub enum ArrayPatternElement {
PropertyAccess { PropertyAccess {
/// The property access where the index element will be stored. /// The property access where the index element will be stored.
access: PropertyAccess, access: PropertyAccess,
/// An optional default value for the variable, in case the index element doesn't exist.
default_init: Option<Expression>,
}, },
/// Pattern represents a `Pattern` in an `Element` of an array pattern. /// Pattern represents a `Pattern` in an `Element` of an array pattern.
@ -680,8 +682,15 @@ impl ToInternedString for ArrayPatternElement {
} }
buf buf
} }
Self::PropertyAccess { access } => { Self::PropertyAccess {
format!(" {}", access.to_interned_string(interner)) access,
default_init,
} => {
let mut buf = format!(" {}", access.to_interned_string(interner));
if let Some(init) = default_init {
buf.push_str(&format!(" = {}", init.to_interned_string(interner)));
}
buf
} }
Self::Pattern { Self::Pattern {
pattern, pattern,
@ -723,9 +732,18 @@ impl VisitWith for ArrayPatternElement {
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
} }
Self::PropertyAccess { access } | Self::PropertyAccessRest { access } => { Self::PropertyAccess {
visitor.visit_property_access(access) access,
default_init,
} => {
try_break!(visitor.visit_property_access(access));
if let Some(expr) = default_init {
visitor.visit_expression(expr)
} else {
ControlFlow::Continue(())
}
} }
Self::PropertyAccessRest { access } => visitor.visit_property_access(access),
Self::Pattern { Self::Pattern {
pattern, pattern,
default_init, default_init,
@ -762,9 +780,18 @@ impl VisitWith for ArrayPatternElement {
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
} }
Self::PropertyAccess { access } | Self::PropertyAccessRest { access } => { Self::PropertyAccess {
visitor.visit_property_access_mut(access) access,
default_init,
} => {
try_break!(visitor.visit_property_access_mut(access));
if let Some(expr) = default_init {
visitor.visit_expression_mut(expr)
} else {
ControlFlow::Continue(())
}
} }
Self::PropertyAccessRest { access } => visitor.visit_property_access_mut(access),
Self::Pattern { Self::Pattern {
pattern, pattern,
default_init, default_init,

11
core/engine/src/bytecompiler/declaration/declaration_pattern.rs

@ -240,10 +240,19 @@ impl ByteCompiler<'_> {
} }
self.emit_binding(def, ident.to_js_string(self.interner())); self.emit_binding(def, ident.to_js_string(self.interner()));
} }
PropertyAccess { access } => { PropertyAccess {
access,
default_init,
} => {
self.access_set(Access::Property { access }, false, |compiler, _level| { self.access_set(Access::Property { access }, false, |compiler, _level| {
compiler.emit_opcode(Opcode::IteratorNextWithoutPop); compiler.emit_opcode(Opcode::IteratorNextWithoutPop);
compiler.emit_opcode(Opcode::IteratorValueWithoutPop); compiler.emit_opcode(Opcode::IteratorValueWithoutPop);
if let Some(init) = default_init {
let skip = compiler.emit_opcode_with_operand(Opcode::JumpIfNotUndefined);
compiler.compile_expr(init, true);
compiler.patch_jump(skip);
}
}); });
} }
// BindingElement : BindingPattern Initializer[opt] // BindingElement : BindingPattern Initializer[opt]

Loading…
Cancel
Save