From eac71e7c641c8e0079d6ef7470953db1fe344719 Mon Sep 17 00:00:00 2001 From: raskad <32105367+raskad@users.noreply.github.com> Date: Wed, 13 Mar 2024 03:34:36 +0100 Subject: [PATCH] Add default value for descructing property access arrays --- core/ast/src/expression/literal/array.rs | 2 + core/ast/src/pattern.rs | 39 ++++++++++++++++--- .../declaration/declaration_pattern.rs | 11 +++++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/core/ast/src/expression/literal/array.rs b/core/ast/src/expression/literal/array.rs index 21f99fa195a..1cadeb08ae9 100644 --- a/core/ast/src/expression/literal/array.rs +++ b/core/ast/src/expression/literal/array.rs @@ -109,6 +109,7 @@ impl ArrayLiteral { AssignTarget::Access(access) => { bindings.push(ArrayPatternElement::PropertyAccess { access: access.clone(), + default_init: Some(assign.rhs().clone()), }); } AssignTarget::Pattern(pattern) => match pattern { @@ -143,6 +144,7 @@ impl ArrayLiteral { Expression::PropertyAccess(access) => { bindings.push(ArrayPatternElement::PropertyAccess { access: access.clone(), + default_init: None, }); } _ => return None, diff --git a/core/ast/src/pattern.rs b/core/ast/src/pattern.rs index 4cfc4b50be2..8a6b19da46e 100644 --- a/core/ast/src/pattern.rs +++ b/core/ast/src/pattern.rs @@ -612,6 +612,8 @@ pub enum ArrayPatternElement { PropertyAccess { /// The property access where the index element will be stored. access: PropertyAccess, + /// An optional default value for the variable, in case the index element doesn't exist. + default_init: Option, }, /// Pattern represents a `Pattern` in an `Element` of an array pattern. @@ -680,8 +682,15 @@ impl ToInternedString for ArrayPatternElement { } buf } - Self::PropertyAccess { access } => { - format!(" {}", access.to_interned_string(interner)) + Self::PropertyAccess { + 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 { pattern, @@ -723,9 +732,18 @@ impl VisitWith for ArrayPatternElement { ControlFlow::Continue(()) } } - Self::PropertyAccess { access } | Self::PropertyAccessRest { access } => { - visitor.visit_property_access(access) + Self::PropertyAccess { + 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 { pattern, default_init, @@ -762,9 +780,18 @@ impl VisitWith for ArrayPatternElement { ControlFlow::Continue(()) } } - Self::PropertyAccess { access } | Self::PropertyAccessRest { access } => { - visitor.visit_property_access_mut(access) + Self::PropertyAccess { + 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 { pattern, default_init, diff --git a/core/engine/src/bytecompiler/declaration/declaration_pattern.rs b/core/engine/src/bytecompiler/declaration/declaration_pattern.rs index a01b6417828..e7b7928f59a 100644 --- a/core/engine/src/bytecompiler/declaration/declaration_pattern.rs +++ b/core/engine/src/bytecompiler/declaration/declaration_pattern.rs @@ -240,10 +240,19 @@ impl ByteCompiler<'_> { } 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| { compiler.emit_opcode(Opcode::IteratorNextWithoutPop); 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]