+
+// ------------------------------ DeconstructingAssignmentNode -----------------
+RegisterID* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
+ return result;
+ RefPtr<RegisterID> initializer = generator.tempDestination(dst);
+ generator.emitNode(initializer.get(), m_initializer);
+ m_bindings->bindValue(generator, initializer.get());
+ return generator.moveToDestinationIfNeeded(dst, initializer.get());
+}
+
+DeconstructionPatternNode::~DeconstructionPatternNode()
+{
+}
+
+void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
+{
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ auto target = m_targetPatterns[i];
+ if (!target)
+ continue;
+ RefPtr<RegisterID> temp = generator.newTemporary();
+ generator.emitLoad(temp.get(), jsNumber(i));
+ generator.emitGetByVal(temp.get(), rhs, temp.get());
+ target->bindValue(generator, temp.get());
+ }
+}
+
+RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
+{
+ if (rhs->isResolveNode()
+ && generator.willResolveToArguments(static_cast<ResolveNode*>(rhs)->identifier())
+ && !generator.symbolTable().slowArguments()) {
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ auto target = m_targetPatterns[i];
+ if (!target)
+ continue;
+
+ RefPtr<RegisterID> temp = generator.newTemporary();
+ generator.emitLoad(temp.get(), jsNumber(i));
+ generator.emitGetArgumentByVal(temp.get(), generator.uncheckedRegisterForArguments(), temp.get());
+ target->bindValue(generator, temp.get());
+ }
+ if (dst == generator.ignoredResult() || !dst)
+ return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
+ Local local = generator.local(generator.vm()->propertyNames->arguments);
+ return generator.moveToDestinationIfNeeded(dst, local.get());
+ }
+ if (!rhs->isSimpleArray())
+ return 0;
+
+ RefPtr<RegisterID> resultRegister;
+ if (dst && dst != generator.ignoredResult())
+ resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
+ ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
+ Vector<ExpressionNode*> elements;
+ for (; elementNodes; elementNodes = elementNodes->next())
+ elements.append(elementNodes->value());
+ if (m_targetPatterns.size() != elements.size())
+ return 0;
+ Vector<RefPtr<RegisterID>> registers;
+ registers.reserveCapacity(m_targetPatterns.size());
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ registers.uncheckedAppend(generator.newTemporary());
+ generator.emitNode(registers.last().get(), elements[i]);
+ if (resultRegister)
+ generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
+ }
+
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ if (m_targetPatterns[i])
+ m_targetPatterns[i]->bindValue(generator, registers[i].get());
+ }
+ if (resultRegister)
+ return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
+ return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
+}
+
+void ArrayPatternNode::toString(StringBuilder& builder) const
+{
+ builder.append('[');
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ if (!m_targetPatterns[i]) {
+ builder.append(',');
+ continue;
+ }
+ m_targetPatterns[i]->toString(builder);
+ if (i < m_targetPatterns.size() - 1)
+ builder.append(',');
+ }
+ builder.append(']');
+}
+
+void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
+{
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ if (DeconstructionPatternNode* node = m_targetPatterns[i].get())
+ node->collectBoundIdentifiers(identifiers);
+ }
+}
+
+void ObjectPatternNode::toString(StringBuilder& builder) const
+{
+ builder.append('{');
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ if (m_targetPatterns[i].wasString) {
+ builder.append('"');
+ escapeStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
+ builder.append('"');
+ } else
+ builder.append(m_targetPatterns[i].propertyName.string());
+ builder.append(":");
+ m_targetPatterns[i].pattern->toString(builder);
+ if (i < m_targetPatterns.size() - 1)
+ builder.append(',');
+ }
+ builder.append('}');
+}
+
+void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
+{
+ for (size_t i = 0; i < m_targetPatterns.size(); i++) {
+ auto& target = m_targetPatterns[i];
+ RefPtr<RegisterID> temp = generator.newTemporary();
+ generator.emitGetById(temp.get(), rhs, target.propertyName);
+ target.pattern->bindValue(generator, temp.get());
+ }
+}
+
+void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
+{
+ for (size_t i = 0; i < m_targetPatterns.size(); i++)
+ m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
+}
+
+void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
+{
+ if (Local local = generator.local(m_boundProperty)) {
+ if (local.isReadOnly()) {
+ generator.emitReadOnlyExceptionIfNeeded();
+ return;
+ }
+ generator.emitMove(local.get(), value);
+ return;
+ }
+ if (generator.isStrictMode())
+ generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
+ RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty);
+ generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
+ generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
+ return;
+}
+
+void BindingNode::toString(StringBuilder& builder) const
+{
+ builder.append(m_boundProperty.string());
+}
+
+void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
+{
+ identifiers.append(m_boundProperty);
+}
+
+RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
+{
+ RELEASE_ASSERT_NOT_REACHED();
+ return 0;
+}