[JSC] add missing RequireObjectCoercible() step in destructuring
https://bugs.webkit.org/show_bug.cgi?id=151596
Patch by Caitlin Potter <caitp@igalia.com> on 2015-12-01
Reviewed by Darin Adler.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitRequireObjectCoercible):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ObjectPatternNode::bindValue):
* tests/stress/destructuring-assignment-require-object-coercible.js: Added.
(testTypeError):
(testOK):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@192899 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 1abbba4..41a64c9 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -3855,4 +3855,17 @@
return result;
}
+void BytecodeGenerator::emitRequireObjectCoercible(RegisterID* value, const String& error)
+{
+ // FIXME: op_jneq_null treats "undetectable" objects as null/undefined. RequireObjectCoercible
+ // thus incorrectly throws a TypeError for interfaces like HTMLAllCollection.
+ RefPtr<Label> target = newLabel();
+ size_t begin = instructions().size();
+ emitOpcode(op_jneq_null);
+ instructions().append(value->index());
+ instructions().append(target->bind(begin, instructions().size()));
+ emitThrowTypeError(error);
+ emitLabel(target.get());
+}
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 07316b1..6ab390e 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -595,6 +595,7 @@
RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
+ void emitRequireObjectCoercible(RegisterID* value, const String& error);
RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node);
void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node);
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index 242738e..6eee442 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -3337,6 +3337,7 @@
void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
{
+ generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
for (size_t i = 0; i < m_targetPatterns.size(); i++) {
auto& target = m_targetPatterns[i];
RefPtr<RegisterID> temp = generator.newTemporary();